<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/"
    xmlns:atom="http://www.w3.org/2005/Atom" xmlns:media="http://search.yahoo.com/mrss/" version="2.0">
    <channel>
        
        <title>
            <![CDATA[ book - freeCodeCamp.org ]]>
        </title>
        <description>
            <![CDATA[ Browse thousands of programming tutorials written by experts. Learn Web Development, Data Science, DevOps, Security, and get developer career advice. ]]>
        </description>
        <link>https://www.freecodecamp.org/news/</link>
        <image>
            <url>https://cdn.freecodecamp.org/universal/favicons/favicon.png</url>
            <title>
                <![CDATA[ book - freeCodeCamp.org ]]>
            </title>
            <link>https://www.freecodecamp.org/news/</link>
        </image>
        <generator>Eleventy</generator>
        <lastBuildDate>Tue, 19 May 2026 10:28:48 +0000</lastBuildDate>
        <atom:link href="https://www.freecodecamp.org/news/tag/book/rss.xml" rel="self" type="application/rss+xml" />
        <ttl>60</ttl>
        
            <item>
                <title>
                    <![CDATA[ The Math Behind Artificial Intelligence: A Guide to AI Foundations [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ "To understand is to perceive patterns." - Isaiah Berlin This is not a math book filled with complex formulas, theorems, and concepts that are hard to grasp. Instead, it’s a detailed guide where we’l ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-math-behind-artificial-intelligence-book/</link>
                <guid isPermaLink="false">695d974f512957bf332d653a</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Mathematics ]]>
                    </category>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ MathJax ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Tiago Capelo Monteiro ]]>
                </dc:creator>
                <pubDate>Tue, 06 Jan 2026 23:14:23 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1767723634484/4748bd8a-26a1-4d9c-89c3-1a6d07bde69e.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <blockquote>
<p>"To understand is to perceive patterns." - Isaiah Berlin</p>
</blockquote>
<p>This is <strong>not</strong> a math book filled with complex formulas, theorems, and concepts that are hard to grasp.</p>
<p>Instead, it’s a detailed guide where we’ll break complex ideas down into simpler terms.</p>
<p>Even if you only have a general understanding of algebra, you should be able to easily follow along.</p>
<h3 id="heading-heres-what-well-cover">Here’s what we’ll cover:</h3>
<ol>
<li><p><a href="#heading-chapter-1-background-on-this-book">Chapter 1: Background on this Book</a></p>
<ul>
<li><p><a href="#heading-the-objective-here">The Objective Here</a></p>
</li>
<li><p><a href="#heading-why-is-this-book-about-ai-different">Why is This Book About AI Different?</a></p>
</li>
<li><p><a href="#heading-let-me-introduce-myself">Let Me Introduce Myself</a></p>
</li>
<li><p><a href="#heading-prerequisites">Prerequisites</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-chapter-2-the-architecture-of-mathematics">Chapter 2: The Architecture of Mathematics</a></p>
<ul>
<li><p><a href="#heading-the-tree-of-mathematics-how-everything-connects">The Tree of Mathematics: How Everything Connects</a></p>
</li>
<li><p><a href="#heading-a-quick-history-of-mathematics-from-counting-to-infinity">A Quick History of Mathematics: From Counting to Infinity</a></p>
</li>
<li><p><a href="#heading-foundations-of-relativity-how-einstein-used-math-to-understand-space-and-time">Foundations of Relativity: How Einstein Used Math to Understand Space and Time</a></p>
</li>
<li><p><a href="#heading-godels-biggest-paradox-can-math-explain-itself">Gödel’s Biggest Paradox: Can Math Explain Itself?</a></p>
</li>
<li><p><a href="#heading-what-about-applied-math-and-engineering">What About Applied Math and Engineering?</a></p>
</li>
<li><p><a href="#heading-code-examples-analytical-and-numerical-approaches">Code Examples: Analytical and Numerical Approaches</a></p>
</li>
<li><p><a href="#heading-the-impact-of-a-grand-unified-theory-of-mathematics">The Impact of a Grand Unified Theory of Mathematics</a></p>
</li>
<li><p><a href="#heading-a-final-lesson-from-history">A Final Lesson From History</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-chapter-3-the-field-of-artificial-intelligence">Chapter 3: The Field of Artificial Intelligence</a></p>
<ul>
<li><p><a href="#heading-what-is-artificial-intelligence">What is Artificial Intelligence?</a></p>
</li>
<li><p><a href="#heading-symbolic-vs-non-symbolic-ai-whats-the-difference">Symbolic vs. Non-symbolic AI: What’s the Difference?</a></p>
</li>
<li><p><a href="#heading-before-ai-control-theory-as-the-first-ai">Before AI: Control Theory as the “First AI”</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-chapter-4-linear-algebra-the-geometry-of-data">Chapter 4: Linear Algebra - The Geometry of Data</a></p>
<ul>
<li><p><a href="#heading-what-are-matrices-and-why-do-they-simplify-equations">What Are Matrices and Why Do They Simplify Equations?</a></p>
</li>
<li><p><a href="#heading-vectors-and-transformations-moving-in-multiple-directions">Vectors and Transformations: Moving in Multiple Directions</a></p>
</li>
<li><p><a href="#heading-linear-independence-dependence-and-rank-why-it-matters">Linear Independence, Dependence, and Rank: Why It Matters</a></p>
</li>
<li><p><a href="#heading-determinants-measuring-space-and-scaling">Determinants: Measuring Space and Scaling</a></p>
</li>
<li><p><a href="#heading-what-are-mathematical-spaces-and-how-do-they-simplify-calculations">What Are Mathematical Spaces and How Do They Simplify Calculations?</a></p>
</li>
<li><p><a href="#heading-eigenvalues-and-eigenvectors-unlocking-hidden-patterns">Eigenvalues and Eigenvectors: Unlocking Hidden Patterns</a></p>
</li>
<li><p><a href="#heading-applications-of-linear-algebra-in-ai-and-control-theory">Applications of Linear Algebra in AI and Control Theory</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-chapter-5-multivariable-calculus-change-in-many-directions">Chapter 5: Multivariable Calculus - Change in Many Directions</a></p>
<ul>
<li><p><a href="#heading-limits-and-continuity-understanding-smooth-change">Limits and Continuity: Understanding Smooth Change</a></p>
</li>
<li><p><a href="#heading-why-are-limits-important-to-understand-derivatives-and-integrals">Why are limits important to understand derivatives and integrals?</a></p>
</li>
<li><p><a href="#heading-derivatives-how-things-change-and-how-fast">Derivatives: How Things Change and How Fast</a></p>
</li>
<li><p><a href="#heading-what-about-integral-calculus">What About Integral Calculus?</a></p>
</li>
<li><p><a href="#heading-applications-in-ai-and-control-theory-calculus-in-action">Applications in AI and Control Theory: Calculus in Action</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-chapter-6-probability-amp-statistics-learning-from-uncertainty">Chapter 6: Probability &amp; Statistics - Learning from Uncertainty</a></p>
<ul>
<li><p><a href="#heading-mean-median-mode-measuring-central-tendency">Mean, Median, Mode: Measuring Central Tendency</a></p>
</li>
<li><p><a href="#heading-variance-and-standard-deviation-measuring-spread">Variance and Standard Deviation: Measuring Spread</a></p>
</li>
<li><p><a href="#heading-what-is-the-normal-distribution-the-bell-curve-of-life">What Is the Normal Distribution? The Bell Curve of Life</a></p>
</li>
<li><p><a href="#heading-how-the-central-limit-theorem-helps-approximate-the-world">How the Central Limit Theorem Helps Approximate the World</a></p>
</li>
<li><p><a href="#heading-bayes-theorem-learning-from-evidence">Bayes Theorem: Learning from Evidence</a></p>
</li>
<li><p><a href="#heading-what-are-markov-models-predicting-the-next-step-one-step-at-a-time">What Are Markov Models? Predicting the Next Step, One Step at a Time</a></p>
</li>
<li><p><a href="#heading-applications-in-ai-and-control-theory-making-decisions-under-uncertainty">Applications in AI and Control Theory: Making Decisions Under Uncertainty</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-chapter-7-optimization-theory-teaching-machines-to-improve">Chapter 7: Optimization Theory - Teaching Machines to Improve</a></p>
<ul>
<li><p><a href="#heading-what-is-optimization-theory">What is Optimization Theory?</a></p>
</li>
<li><p><a href="#heading-why-optimization-drives-learning-in-ai">Why Optimization Drives Learning in AI</a></p>
</li>
<li><p><a href="#heading-simple-optimization-techniques-how-machines-learn-step-by-step">Simple Optimization Techniques: How Machines Learn Step by Step</a></p>
</li>
<li><p><a href="#heading-what-is-adam-the-most-popular-way-ai-models-finds-the-best-learning-path">What is Adam? The Most Popular Way AI Models Finds the Best Learning Path</a></p>
</li>
<li><p><a href="#heading-applications-in-ai-and-control-theory-of-optimization-theory">Applications in AI and Control Theory of Optimization Theory</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-conclusion-where-mathematics-and-ai-meet">Conclusion: Where Mathematics and AI Meet</a></p>
<ul>
<li><p><a href="#heading-mathematics-is-the-foundation-of-ai">Mathematics is the Foundation of AI</a></p>
</li>
<li><p><a href="#heading-the-future-on-device-ai-and-the-democratization-of-ai">The Future: On Device AI and the Democratization of AI</a></p>
</li>
<li><p><a href="#heading-final-reflections">Final Reflections</a></p>
</li>
<li><p><a href="#heading-acknowledgements">Acknowledgements</a></p>
</li>
</ul>
</li>
<li><p><a href="#heading-about-the-author">About the Author</a></p>
</li>
</ol>
<h2 id="heading-chapter-1-background-on-this-book">Chapter 1: Background on this Book</h2>
<h3 id="heading-the-objective-here">The Objective Here</h3>
<p>My objective in this book is simple: Explain the key mathematical ideas you need to grasp in order to deeply understand AI and train machine learning models.</p>
<p>So you might be wondering: Why is it important to have a good math foundation before creating these models?</p>
<p>Well, there are many reasons, but some are:</p>
<ul>
<li><p>It gives you the capacity to understand new AI research on your own.</p>
</li>
<li><p>You can use this same foundation to study other STEM concepts like signal theory and advanced statistical methods.</p>
</li>
<li><p>It helps you understand that AI models are just a mixture of different math ideas working together and gives you insight into how new innovations make LLMs more efficient.</p>
</li>
<li><p>It gives you a foundation so you know how to calibrate AI models and even create derivative models.</p>
</li>
</ul>
<p>These skills are also important for startup founders, especially in Silicon Valley. Many startups begin with APIs or API wrappers but eventually need their own AI solutions.</p>
<p>Outsourcing all AI isn't ideal. This book will help you understand AI foundations so you can design better growth strategies and communicate effectively with investors – especially those who were successful technical co-founders.</p>
<h3 id="heading-why-is-this-book-about-ai-different">Why is This Book About AI Different?</h3>
<p>In this book, we’ll look at AI from an engineering perspective. This differs from the typical computer science approach to AI that most introductory courses take.</p>
<p>In doing so, I won’t spend a lot of time explaining formulas and theorems. Instead, I’ll explain their importance, how and why they are applied the way they are.</p>
<p>In this way, I hope to offer a unique viewpoint that emphasizes the engineering principles and good practices that underlie all modern AI technologies.</p>
<p>I will also explain how many of these strange math ideas make billion dollar industries possible.</p>
<p>We’ll start with the fundamentals: the structure of the areas of mathematics and AI. After that, we’ll look at the four subareas of math that make AI possible:</p>
<ul>
<li><p>Linear Algebra</p>
</li>
<li><p>Calculus</p>
</li>
<li><p>Probability Theory and Statistics</p>
</li>
<li><p>Optimization Theory</p>
</li>
</ul>
<p>After going through all the math, we’ll connect it with the foundation of ChatGPT and all of these large language models.</p>
<p>This way, you’ll get a basic foundation in key math concepts that, when mixed together like the ingredients of a cake, make all AI models possible.</p>
<p>By knowing where the ideas come from, you’ll develop a system-level understanding of AI and a first-principles approach.</p>
<p>So just keep in mind that, even though concepts like integral calculus and eigenvalues/eigenvectors might not be widely used in AI, they’ll help you develop these system-level and first-principle approaches.</p>
<p>Also, this book will be a work in progress. After its first release, I’ll seek feedback on things I need to perfect, chapters to add, and so on.</p>
<p>Here is my email for any feedback you might have: <a href="mailto:monteiro.t@northeastern.edu">monteiro.t@northeastern.edu</a></p>
<p>And here is the book’s GitHub repository with all code: <a href="https://github.com/tiagomonteiro0715/The-Math-Behind-Artificial-Intelligence-A-Guide-to-AI-Foundations">https://github.com/tiagomonteiro0715/The-Math-Behind-Artificial-Intelligence-A-Guide-to-AI-Foundations</a></p>
<h3 id="heading-let-me-introduce-myself">Let Me Introduce Myself</h3>
<p>My name is Tiago Monteiro, an electrical and computer engineer and AI master's degree student at Northeastern University's Silicon Valley campus. I have authored 20+ articles with 240K+ views here on freeCodeCamp on math, AI, and tech.</p>
<p>If you’d like to know more about my background, I’ll share that at the end of the book.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>In terms of minimum requirements, you only need to know the basics of mathematics and programming:</p>
<ul>
<li><p>Basic algebra and what functions and the coordinate system are.</p>
</li>
<li><p>You should be able to read Python code and understand things like variables, functions, and loops.</p>
</li>
</ul>
<h2 id="heading-chapter-2-the-architecture-of-mathematics">Chapter 2: The Architecture of Mathematics</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766099739986/049ff3c0-0150-495e-97e9-4f16f3861058.png" alt="Cover of the chapter the architecture of mathematics" style="display:block;margin:0 auto" width="1920" height="1080" loading="lazy">

<p>Math is more than numbers. It’s the science of locating complex patterns that shape our world. To truly understand math, we must look beyond numbers and formulas to grasp its structures.</p>
<p>This chapter aims to show math as a growing tree of ideas, a living system of logic, not just formulas to memorize. With analogies, history, and code examples, I want to help you understand math deeply and how to apply it to programming.</p>
<p>I’ve included code examples to connect theory and practice, showing how math ideas apply to real problems. Whether you're new to advanced math or are more experienced, these examples will help you apply math in programming.</p>
<p>This way, before we start going over the different math pillars that sustain AI, you will understand the structure of the field.</p>
<h3 id="heading-the-tree-of-mathematics-how-everything-connects">The Tree of Mathematics: How Everything Connects</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765001557970/7ac6c8c8-d0fd-4a67-be6a-6d8b9a1a6615.jpeg" alt="Seeing a tree from its root to a tree" style="display:block;margin:0 auto" width="2000" height="1299" loading="lazy">

<p>Photo by <a href="https://www.pexels.com/photo/bottom-view-of-green-leaved-tree-during-daytime-91153/">Lerkrat Tangsri</a></p>
<p>Imagine math as a vast, ever-growing tree.</p>
<p>The roots are the foundations: logic and set theory. From these roots, the main fields emerge: arithmetic, algebra, geometry, and analysis.</p>
<p>As the tree branches out, new subfields like topology and abstract algebra appear. Sometimes branches connect with each other.</p>
<p>This tree keeps growing in many directions. History shows that sometimes it grows rapidly due to scientific discoveries, while at other times, growth is slow.</p>
<p>And you might wonder: How many more branches and connections between them will keep appearing?</p>
<h3 id="heading-a-quick-history-of-mathematics-from-counting-to-infinity">A Quick History of Mathematics: From Counting to Infinity</h3>
<p>The first mathematical ideas emerged independently in ancient civilizations, such as:</p>
<ul>
<li><p>India's invention of zero</p>
</li>
<li><p>Islamic algebraic advances</p>
</li>
<li><p>Greek geometric rigor</p>
</li>
</ul>
<p>Great mathematicians developed and shared these ideas through writing and lectures. Over time, new generations built on these ideas, creating new branches of mathematics. This endless growth is why Isaac Newton wrote to Robert Hooke in 1675:</p>
<blockquote>
<p>“If I have seen further, it is by standing on the shoulders of giants.”</p>
</blockquote>
<p>He meant that by working from previous knowledge, he was able to create and (re)discover new ideas.</p>
<p>Yet, the real power of math lies in practicing it over and over and studying it more and more deeply.</p>
<p>As one of my professors once pointed out:</p>
<blockquote>
<p><em>“More important than knowing the theorems is knowing the ideas behind them and the history of how they were created.”</em></p>
</blockquote>
<p>To solve problems, it's often necessary to think from first principles, and math teaches this. Math is not just an academic topic. It’s a global language for scientists and engineers.</p>
<p>By preserving and sharing it, new math can grow from old ideas, allowing the tree to keep expanding.</p>
<h3 id="heading-foundations-of-relativity-how-einstein-used-math-to-understand-space-and-time">Foundations of Relativity: How Einstein Used Math to Understand Space and Time</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766903578928/a4102586-cb63-4410-8793-72950145726d.jpeg" alt="A satellite in space" style="display:block;margin:0 auto" width="2274" height="1506" loading="lazy">

<p>Photo by <a href="https://www.pexels.com/photo/gray-and-white-satellite-41006/">Pixabay</a></p>
<p>Albert Einstein developed the general and special theories of relativity, which impact:</p>
<ul>
<li><p>GPS and global communication</p>
</li>
<li><p>Satellite telecommunications</p>
</li>
<li><p>Space exploration and satellite launches</p>
</li>
</ul>
<p>And more.</p>
<p>But this was only possible by combining geometry with calculus, known as <strong>differential geometry.</strong> This field evolved over centuries, thanks to many great mathematicians. Here are a few of them, though the list is not exhaustive:</p>
<ul>
<li><p><strong>Euclid (circa 300 BCE):</strong> Contributed to geometry, laying the groundwork for later mathematical systems</p>
</li>
<li><p><strong>Archimedes (circa 287–212 BCE):</strong> Pioneered the understanding of volume, surface area, and the principles of mechanics</p>
</li>
<li><p><strong>René Descartes (1596–1650):</strong> Developed Cartesian coordinates and analytical geometry</p>
</li>
<li><p><strong>Isaac Newton (1642–1727) &amp; Gottfried Wilhelm Leibniz (1646–1716):</strong> Newton’s laws of motion and gravitation, alongside Leibniz’s development of calculus, formed the basis of classical mechanics that Einstein sought to extend and modify in his theory of relativity.</p>
</li>
<li><p><strong>Leonhard Euler (1707–1783):</strong> Contributed to the development of differential equations, which are essential in the mathematical foundations of physics.</p>
</li>
<li><p><strong>Gaspard Monge (1746–1818):</strong> The father of differential geometry and pioneer in descriptive geometry</p>
</li>
<li><p><strong>Carl Friedrich Gauss (1777–1855):</strong> Made groundbreaking advances in geometry, including the concept of curved surfaces.</p>
</li>
<li><p><strong>Bernhard Riemann (1826–1866):</strong> Introduced Riemannian geometry, a branch of differential geometry.</p>
</li>
</ul>
<p>Going back to Albert Einstein, he saw what no one else in his time saw, thanks to these great math giants and countless others.</p>
<h3 id="heading-godels-biggest-paradox-can-math-explain-itself">Gödel’s Biggest Paradox: Can Math Explain Itself?</h3>
<p>The biggest paradox in math, discovered by Kurt Gödel, is his incompleteness theorems. They show that in any consistent formal system capable of simple arithmetic, there are true statements that cannot be proven within the system.</p>
<p>This means there are limits to what can be proven as true or false. For mathematicians, this implies that some truths are beyond formal proofs, yet we assume they are true. It demonstrates that no matter how much effort or AI is used, some things remain unprovable, known only through approximations and non-exact methods.</p>
<h3 id="heading-what-about-applied-math-and-engineering">What About Applied Math and Engineering?</h3>
<p>Applied math and engineering involve adapting the pure math ideas in real-world scenarios.</p>
<p>Actually, in many cases, it’s the combination of many math ideas.</p>
<p>Let’s consider some examples:</p>
<ul>
<li><p>In <strong>harmonic analysis</strong>, Laplace, Fourier, and Z-transforms are a way to see the same thing in a new domain to get new insights. In this case, integrals are used to make this mapping possible.</p>
</li>
<li><p><strong>Principal component analysis (PCA)</strong> is a widely used tool in data science. Yet, it is a mixture of linear algebra (in PCA, eigenvalues) with optimization (order eigenvalues that represent more data with less data) in order to make datasets shorter.</p>
</li>
<li><p>In <strong>machine learning</strong>, logistic regression is a mixture of calculus with statistics and probability.</p>
</li>
<li><p>In <strong>deep learning</strong>, neural networks are just many matrices multiplying and updating themselves that adapt to model a dataset representing a system. This optimization of matrix values happens with activation functions, a gradient descent-based optimization method (tells how much values need to change), and backpropagation (applies those alterations to all matrix values).</p>
</li>
</ul>
<p>But the best example of this fusion of math in engineering is in <a href="https://www.freecodecamp.org/news/basic-control-theory-with-python/">control theory</a>. Control theory is the study of the architecture of systems. From trains to cars to airplanes, everything is based on control theory. It’s everywhere, in nearly all modern electronic devices. In electric circuits, control theory is also used heavily to guarantee circuit stability in the face of electric disturbances.</p>
<p>So as you can probably start to see, many of the tools we now have are just a mixture of many pure math ideas – like different recipes. In essence, applied math is the application of pure math as “ingredients“ in "recipes" to solve problems.</p>
<p>So, we’ve explored the structure and evolution of mathematics. But it’s important to see how we can apply these ideas in real life. Pure math makes the framework, and applied math applies that framework to solve problems. To understand this, we’ll examine two code examples that show how you can use math ideas as programming tools.</p>
<h3 id="heading-code-examples-analytical-and-numerical-approaches">Code Examples: Analytical and Numerical Approaches</h3>
<p>These code examples demonstrate a couple ways you can use Python to solve math equations.</p>
<p>In the first code example, we’ll solve the problem in the same way that kids in school solve math exercises: essentially, by hand with a pencil. In the second example, we’ll solve the problem using numerical analysis.</p>
<h4 id="heading-example-1-solve-a-problem-analytically">Example 1: Solve a Problem Analytically</h4>
<p>In this problem, we need to find the values of the variables x and y. So we’ll be moving variables from left to right to find their values.</p>
<p>When we solve math problems analytically, like we did in school, we are manipulating symbols to get exact values. Often these symbols are x, y, and z.</p>
<p>The code below solves a system of two equations with two unknowns variables, x and y.</p>
<p>We will use the <a href="https://www.sympy.org">SymPy</a> Python library to do this. It’s mainly used for symbolic mathematics.</p>
<pre><code class="language-python">from sympy import symbols, Eq, solve

x, y = symbols('x y')
eq1 = Eq(2*x + 3*y, 6)
eq2 = Eq(-x + y, 1)

solution = solve((eq1, eq2), (x, y))
print(solution)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747160359386/7a21cddc-f4ba-4f9f-afa0-d1cc11fb27d6.png" alt="Image of the equations and analytical method in Python" style="display:block;margin:0 auto" width="2080" height="1224" loading="lazy">

<p>Once again with this code we are finding the values of the variables x and y.</p>
<p>Essentially, we’re finding x and y based on this equation:</p>
<p>$$\begin{align} 2x + 3y &amp;= 6 \ -x + y &amp;= 1 \end{align}$$</p>
<p>Which gives us the following result:</p>
<pre><code class="language-python">{x: 3/5, y: 8/5}
</code></pre>
<p>Or:</p>
<ul>
<li><p>x= 0.6</p>
</li>
<li><p>y = 1.6</p>
</li>
</ul>
<p>When we say that we’re solving this analytically, it means that we’re finding an exact mathematical solution using formulas or equations.</p>
<p>But many times, problems are harder and can be solved by adding symbols to the right or left of the equation. Sometimes, there can be so many symbols and transformed versions of them, with things like derivatives and integrals, that it can become very hard to manage and takes a lot of time.</p>
<p>For example, let’s look at this partial differential equation:</p>
<p>$$\begin{cases} \frac{\partial u}{\partial t} = \alpha \frac{\partial^2 u}{\partial x^2}, &amp; 0 &lt; x &lt; L, , t &gt; 0 \ u(0,t) = 0, &amp; t &gt; 0 \ u(L,t) = 0, &amp; t &gt; 0 \ u(x,0) = f(x), &amp; 0 &lt; x &lt; L \end{cases}$$</p>
<p>It can be solved with an analytical method call separation of variables.</p>
<p>But it requires many steps, and it’s easy to make mistakes. Even engineers who learned this often struggle to remember the process later.</p>
<p>When I first encountered this type of math exercise in my electrical and computer engineering degree back in Portugal, it took me 20 to 30 minutes to solve it.</p>
<p>For this reason, there's a branch of mathematics called numerical analysis that focuses on finding approximations of existing formulas. It helps solve problems faster. This is the method we'll explore next.</p>
<h4 id="heading-example-2-solve-numerically-approximation">Example 2: Solve Numerically (Approximation)</h4>
<p>Now let’s solve a different problem: we’re going to find the values of each of the 5 variables:</p>
<p>$$\begin{bmatrix} 3 &amp; 2 &amp; -1 &amp; 4 &amp; 5 \ 1 &amp; 1 &amp; 3 &amp; 2 &amp; -2 \ 4 &amp; -1 &amp; 2 &amp; 1 &amp; 0 \ 5 &amp; 3 &amp; -2 &amp; 1 &amp; 1 \ 2 &amp; -3 &amp; 1 &amp; 3 &amp; 4 \end{bmatrix} \times \begin{bmatrix} x_1 \ x_2 \ x_3 \ x_4 \ x_5 \end{bmatrix} = \begin{bmatrix} 12 \ 5 \ 7 \ 9 \ 10 \end{bmatrix}$$</p>
<p>Solving this by hand will take some time…but with Python code, it’s very fast.</p>
<p>We’ll also use the <a href="https://scipy.org">SciPy</a> Python library for this example.</p>
<p>Let’s solve the system numerically:</p>
<pre><code class="language-python">import numpy as np
from scipy.linalg import solve

A = np.array([[3, 2, -1, 4, 5],
              [1, 1, 3, 2, -2],
              [4, -1, 2, 1, 0],
              [5, 3, -2, 1, 1],
              [2, -3, 1, 3, 4]])

b = np.array([12, 5, 7, 9, 10])

solution = solve(A, b)

print(solution)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1747160347486/d1f17aa6-b288-4e41-9be7-0810c45e778c.png" alt="Image of equations and numerical method" style="display:block;margin:0 auto" width="2080" height="1764" loading="lazy">

<p>Which corresponds to this operation:</p>
<p>$$\begin{bmatrix} 3 &amp; 2 &amp; -1 &amp; 4 &amp; 5 \ 1 &amp; 1 &amp; 3 &amp; 2 &amp; -2 \ 4 &amp; -1 &amp; 2 &amp; 1 &amp; 0 \ 5 &amp; 3 &amp; -2 &amp; 1 &amp; 1 \ 2 &amp; -3 &amp; 1 &amp; 3 &amp; 4 \end{bmatrix} \times \begin{bmatrix} x_1 \ x_2 \ x_3 \ x_4 \ x_5 \end{bmatrix} = \begin{bmatrix} 12 \ 5 \ 7 \ 9 \ 10 \end{bmatrix}$$</p>
<p>Again, it takes time to solve this and it’s very easy to make a simple mistake.</p>
<p>But in this code example, this line of code:</p>
<pre><code class="language-python">solution = solve(A, b)
</code></pre>
<p>Uses the <code>solve</code> method from SciPy:</p>
<pre><code class="language-python">from scipy.linalg import solve
</code></pre>
<p>It’s a method that helps you find the values of x in an equation A⋅x=b, where A is a square grid of numbers and b is a list of numbers. That gives us the following:</p>
<pre><code class="language-python">[ 1.35022026 -0.79955947 -1.17180617  3.14317181 -0.83920705]
</code></pre>
<p>Which corresponds to:</p>
<p>$$\begin{bmatrix} x_1 \ x_2 \ x_3 \ x_4 \ x_5 \end{bmatrix} = \begin{bmatrix} 1.35022026 \ -0.79955947 \ -1.17180617 \ 3.14317181 \ -0.83920705 \end{bmatrix}$$</p>
<p>And is the same thing as:</p>
<p>$$\begin{align} x_1 &amp;= 1.35022026 \ x_2 &amp;= -0.79955947 \ x_3 &amp;= -1.17180617 \ x_4 &amp;= 3.14317181 \ x_5 &amp;= -0.83920705 \end{align}$$</p>
<h4 id="heading-why-these-two-approaches-matter">Why These Two Approaches Matter</h4>
<p>We have solved two mathematical problems in two different ways:</p>
<ul>
<li><p>Analytical: Exact solutions through algebraic manipulation</p>
</li>
<li><p>Numerical: Approximate solutions using algorithms</p>
</li>
</ul>
<p>In engineering and in AI, we are constantly choosing between these approaches.</p>
<p>When training AI models with millions of parameters, analytical solutions are impossible. This is why, in these cases, we need numerical approaches.</p>
<p>When creating math theorems, we need analytical precision to make sure it is the best possible solution.</p>
<p>This is one of the many things an engineering degree teaches you: often, in the real world, it’s better to just write some code to solve a problem than to actually solve it by hand with math. Other times, the best solution is to just think in first principles and from there create new theorems to solve a problem.</p>
<p>Now let's step out of the code examples and see how different branches of mathematics connect.</p>
<h3 id="heading-the-impact-of-a-grand-unified-theory-of-mathematics">The Impact of a Grand Unified Theory of Mathematics</h3>
<p>Is it possible to unify all math?</p>
<p>In theory, yes. This is known as the Grand Unified Theory of Mathematics. It's the idea that all different areas of math can be linked together to discover deeper patterns in mathematics.</p>
<p>The <a href="https://en.wikipedia.org/wiki/Langlands_program">Langlands program</a> is trying to make this unification possible. It’s an attempt to interconnect the largest parts of the big tree of math to uncover new patterns in math.</p>
<p>With a Grand Unified Theory of Mathematics, we would be able to understand how every branch of the tree connects with the others and all the relationships between them.</p>
<h4 id="heading-whats-the-value-of-this-big-unification-for-society">What’s the Value of this Big Unification for Society?</h4>
<p>By studying history, we can find patterns. The unification of various fields has created many massive impacts on society, such as:</p>
<ul>
<li><p>In the 19th century, James Clerk Maxwell united the fields of electricity and magnetism with his famous Maxwell equations. This allowed the creation of radios and electric grids around the globe. In turn, it served as a foundation for all technological progress in the 20th and 21st century.</p>
</li>
<li><p>In the 20th century, the unification of algebra with logic led to the rise of digital systems. In turn, digital systems gave rise to processors and the evolution of computers and the modern laptop.</p>
</li>
<li><p>Also in the 20th century, the unification of probability and communication led to information theory. This became the foundation for the internet. This unification was carried out by a great mathematician named Claude Shannon.</p>
</li>
</ul>
<p>In the end, a grand unified theory of mathematics could be one of the biggest achievements in modern society.</p>
<p>In AI, it could help unify all machine learning models in a common architecture. This would help accelerate the development of new AI models and could also open the door to new material science advances.</p>
<p>It could help reveal – with math – the deep patterns we still haven’t found in these fields. Just as uniting electricity and magnetism led to modern technology, a unified math framework would lead to a wave of innovation.</p>
<h3 id="heading-a-final-lesson-from-history">A Final Lesson From History</h3>
<p>From Greek geometry to AI, math has grown like a tree over centuries. By understanding its structure, it’s possible to see its role in finding the patterns of our universe.</p>
<p>I hope I was able to make you see math in this way. I hope you can also see that the unification of scientific fields helps lay the foundations for the creation of new innovations to help society go forward.</p>
<p>Many major societal transformations only came to be thanks to abstract math ideas. When these are shared and refined, they become the hidden architecture of progress in society. Innovation begins when disconnected ideas are united, well-linked, and widely shared.</p>
<h2 id="heading-chapter-3-the-field-of-artificial-intelligence">Chapter 3: The Field of Artificial Intelligence</h2>
<h3 id="heading-what-is-artificial-intelligence">What is Artificial Intelligence?</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765001693682/bbec3565-643f-421f-b32e-3de62285a2c0.jpeg" alt="A man playing chess against a robot" style="display:block;margin:0 auto" width="5192" height="3466" loading="lazy">

<p>Photo by <a href="https://www.pexels.com/photo/elderly-man-thinking-while-looking-at-a-chessboard-8438918/">Pavel Danilyuk</a></p>
<p>The term Artificial Intelligence was born from the work of John McCarthy, who is often called the "father of AI."</p>
<p>He used it when he, along with Marvin Minsky, Nathaniel Rochester, and Claude Shannon, proposed the famous Dartmouth Summer Research Project on Artificial Intelligence in 1956.</p>
<p>Artificial intelligence was defined, in the Dartmouth Conference, as:</p>
<blockquote>
<p><em>“Every aspect of learning or any other feature of intelligence can in principle be so precisely described that a machine can be made to simulate it.”</em></p>
</blockquote>
<p>Since then, the field has evolved in waves of innovation, from early rules-based systems to modern neural networks.</p>
<p>But over time, rather than creating <a href="https://en.wikipedia.org/wiki/Artificial_general_intelligence">general intelligence</a>, most AI systems have been designed to excel at narrow tasks.</p>
<p>For example:</p>
<ul>
<li><p>Chess-playing programs like Deep Blue that defeated world champion Garry Kasparov</p>
</li>
<li><p>Image recognition systems that can identify objects in photographs with impressive accuracy</p>
</li>
<li><p>Natural language processing models that can translate between languages</p>
</li>
<li><p>Game-playing AI like AlphaGo that mastered the ancient game of Go</p>
</li>
</ul>
<h4 id="heading-artificial-general-intelligence-isnt-yet-here">Artificial General Intelligence isn’t yet here</h4>
<p>Only very narrow AI models have demonstrated human-level or superhuman performance in their narrow domains.</p>
<p>In my view, and as we will see in this book, AGI will be the combination and interaction of different large language models interacting with each other and with the tools available to them.</p>
<h3 id="heading-symbolic-vs-non-symbolic-ai-whats-the-difference">Symbolic vs. Non-symbolic AI: What’s the Difference?</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1755906822438/f639efd3-3f8b-45a7-ad2d-d1795d772947.png" alt="Image comparing artificial general intelligence with narrow AI and, inside narrow AI, non-symbolic AI and symbolic AI circles" style="display:block;margin:0 auto" width="1858" height="1041" loading="lazy">

<h4 id="heading-what-is-symbolic-ai">What is Symbolic AI?</h4>
<p>Symbolic AI refers to the creation of a program based on many rules and symbols to simulate how humans think.</p>
<p>It uses symbols to represent concepts (like farms and distributors) and logical rules to reason about them.</p>
<p>The specific data about your domain is called facts. Facts are the pieces of information the rules operate on. For example, a fact might be "green_acres has high water usage and good pH levels."</p>
<p>Also, imagine someone wants to optimize farm distribution logistics. The symbols would represent farms, distributors, and transport methods. Then the rules would be:</p>
<ul>
<li><p>If the farm has high water usage and good pH levels, then classify it as high-yield producer</p>
</li>
<li><p>If a high-yield producer and distributor has low demand, then prioritize direct connection</p>
</li>
<li><p>If a direct connection is needed, then select transport with lowest environmental impact</p>
</li>
</ul>
<p>The facts would be the actual data like "farm X has high water usage" or "distributor Y has low demand."</p>
<p>This way, the system combines these rules and facts through logical reasoning to make decisions. A very popular programming language we use in this field is called Prolog that was designed to create rule-based systems.</p>
<p><strong>Symbolic AI program: Manage agricultural networks with a Prolog program.</strong></p>
<p>Let’s look at an example project to understand this more clearly. The project we’ll examine is called SymbolicAIHarvest. It was part of a course at NOVA University during my undergraduate studies in Electrical and Computer Engineering. The course was titled "Modelation of Data in Engineering."</p>
<p>SymbolicAIHarvest is an AI system developed with Prolog to manage agricultural networks. <a href="https://github.com/tiagomonteiro0715/SymbolicAIHarvest">Here’s the project</a> on GitHub so you can check it out.</p>
<p>The project optimizes farm operations using rule-based reasoning. It monitors sensors for real-time data and improves route planning for machinery. It also coordinates produce movement to reduce delays and waste, enhancing productivity and sustainability.</p>
<p>Understanding the code below is not a priority for this book. I just want to show you an example of all the facts of the project:</p>
<pre><code class="language-plaintext">% FARMERS(owner)
farmer(ana).
farmer(asdrubal).
farmer(miguel).
farmer(joao).
farmer(teresinha).
farmer(victor).
farmer(carlos).
farmer(anabela).

% FARMS(name, owner, region, type)
farm(q1, ana, alentejo, vinha).
farm(q2, ana, alentejo, olival).
farm(q3, asdrubal, lisboa, cenoureira).
farm(q4, asdrubal, lisboa, milharal).
farm(q5, asdrubal, lisboa, vinha).
farm(q6, miguel, evora, trigal).
farm(q7, miguel, evora, cenoureia).
farm(q8, miguel, evora, vinha).
farm(q9, miguel, evora, morangueira).
farm(q10, joao, porto, vinha).
farm(q11, joao, porto, trigal).
farm(q12, joao, porto, cenoureira).
farm(q13, teresinha, algarve, olival).
farm(q14, teresinha, algarve, vinha).
farm(q15, victor, setubal, olival).
farm(q16, victor, setubal, vinha).
farm(q17, victor, setubal, trigal).
farm(q18, carlos, sintra, milharal).
farm(q19, carlos, sintra, vinha).
farm(q20, anabela, coina, milharal).
farm(q21, anabela, coina, olival).
farm(q22, anabela, coina, trigal).

% SENSOR READINGS(name, type, value)
sensor_reading(q1,humidity,28).
sensor_reading(q2,humidity,35).
sensor_reading(q3,humidity,42).
sensor_reading(q4,humidity,38).
sensor_reading(q5,humidity,33).
sensor_reading(q6,humidity,45).
sensor_reading(q7,humidity,30).
sensor_reading(q8,humidity,36).
sensor_reading(q9,humidity,50).
sensor_reading(q10,humidity,41).
sensor_reading(q11,humidity,40).
sensor_reading(q12,humidity,44).
sensor_reading(q13,humidity,32).
sensor_reading(q14,humidity,29).
sensor_reading(q15,humidity,47).
sensor_reading(q16,humidity,39).
sensor_reading(q17,humidity,53).
sensor_reading(q18,humidity,27).
sensor_reading(q19,humidity,24).
sensor_reading(q20,humidity,31).
sensor_reading(q21,humidity,37).
sensor_reading(q22,humidity,46).
sensor_reading(q1, temperature, 25).
sensor_reading(q2, temperature, 25).
sensor_reading(q3, temperature, 25).
sensor_reading(q4, temperature, 25).
sensor_reading(q5, temperature, 25).
sensor_reading(q6, temperature, 25).
sensor_reading(q7, temperature, 25).
sensor_reading(q8, temperature, 25).
sensor_reading(q9, temperature, 25).
sensor_reading(q10, temperature, 25).
sensor_reading(q11, temperature, 25).
sensor_reading(q12, temperature, 25).
sensor_reading(q13, temperature, 25).
sensor_reading(q14, temperature, 25).
sensor_reading(q15, temperature, 25).
sensor_reading(q16, temperature, 25).
sensor_reading(q17, temperature, 25).
sensor_reading(q18, temperature, 25).
sensor_reading(q19, temperature, 25).
sensor_reading(q20, temperature, 25).
sensor_reading(q21, temperature, 25).
sensor_reading(q22, temperature, 25).
sensor_reading(q1, water, 47000).
sensor_reading(q2, water, 52500).
sensor_reading(q3, water, 39000).
sensor_reading(q5, water, 61000).
sensor_reading(q8, water, 58000).
sensor_reading(q10, water, 43000).
sensor_reading(q13, water, 72000).
sensor_reading(q16, water, 49000).
sensor_reading(q18, water, 35000).
sensor_reading(q21, water, 66500).
sensor_reading(q1, ph, 6.5).
sensor_reading(q2, ph, 4.7).
sensor_reading(q3, ph, 8.2).
sensor_reading(q4, ph, 7.0).
sensor_reading(q5, ph, 5.1).
sensor_reading(q6, ph, 8.0).
sensor_reading(q7, ph, 4.5).

% DISTRIBUTORS (name, region, capacity, demand level)
distributor(d1, alentejo, 1000, 2).
distributor(d2, lisboa, 800, 1).
distributor(d3, evora, 1200, 3).
distributor(d4, porto, 900, 2).
distributor(d5, algarve, 700, 2).
distributor(d6, setubal, 1100, 1).
distributor(d7, sintra, 950, 2).
distributor(d8, coina, 1000, 1).

% TRANSPORTS (name, capacity, type, autonomy, region, impact)
transport(t1, 1000, fossil, 100, alentejo, 3).
transport(t2, 500, electric, 10, alentejo, 1).
transport(t3, 800, fossil, 400, algarve, 5).
transport(t4, 700, hybrid, 300, setubal, 2).
transport(t5, 150, electric, 340, coina, 1).
transport(t6, 700, fossil, 220, porto, 3).
transport(t7, 900, hybrid, 350, evora, 2).
transport(t8, 1000, electric, 170, sintra, 1).

% Connections based on graph image

% Top of the network
link(q2, d1, 5).
link(q1, d1, 7).
link(q3, d1, 6).

% Network center
link(q3, q4, 8).
link(q4, d2, 6).
link(q4, d3, 7).
link(q4, q5, 5).
link(q4, d4, 6).

% Additional connections
link(q2, d2, 8).
link(q3, d3, 7).
</code></pre>
<p>This Prolog code models an agricultural supply chain system that has:</p>
<ul>
<li><p>Farmers</p>
</li>
<li><p>Farms</p>
</li>
<li><p>Sensors Readings</p>
</li>
<li><p>Distributors</p>
</li>
<li><p>Transports</p>
</li>
</ul>
<p>In addition, in this part of the code on the facts of the system:</p>
<pre><code class="language-plaintext">% Top of the network
link(q2, d1, 5).
link(q1, d1, 7).
link(q3, d1, 6).

% Network center
link(q3, q4, 8).
link(q4, d2, 6).
link(q4, d3, 7).
link(q4, q5, 5).
link(q4, d4, 6).

% Additional connections
link(q2, d2, 8).
link(q3, d3, 7).
</code></pre>
<p>We connect farms with distributors. This way, we can see that between the farm <code>q1</code> and distributor <code>d1</code> is a distance of 7k. This makes it possible to find/create algorithms to find the shortest path between them.</p>
<p>In the end, symbolic AI just creates programs based on a context and rules applied to that context.</p>
<h4 id="heading-what-is-non-symbolic-ai">What is Non-Symbolic AI?</h4>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1755906892854/197f7bc3-8c05-46f2-aa2a-99dbaa733a9a.png" alt="Non-symbolic AI with a circle titled machine learning inside. Inside the machine learning circle is another circle with the text deep learning." style="display:block;margin:0 auto" width="1711" height="951" loading="lazy">

<p>Non symbolic AI doesn’t use symbols or rules to think. Instead, it’s data driven. In other words, it learns patterns from large datasets. This is the approach used in machine learning and deep learning.</p>
<p>When we create an AI model, we can associate it with an API (Application Programming Interface) so that we can use the AI model in websites, applications, and other systems. Basically, the trained AI model is set up behind an API endpoint. An API endpoint is like a web service that lets other applications send requests to the model and get responses back.</p>
<p>For example, when you use ChatGPT in a web browser, your messages are sent through OpenAI's API to their language model, which processes your input and sends back a response.</p>
<p>An AI agent is a software program that can autonomously perform tasks by making decisions and taking actions to achieve specific goals.</p>
<p>Unlike basic chatbots that only reply to questions, AI agents can plan steps, use tools, and work towards achieving complex goals. They do this by combining language models with extra features like accessing outside data or working with other AI agents.</p>
<p><a href="https://github.com/tiagomonteiro0715/ai-content-lab">Here’s an example</a> of a non-symbolic AI agent project I worked on. I developed it using the <a href="https://www.crewai.com/">crewAI</a> Python library and the OpenAI API, one of the most popular libraries for creating AI agents.</p>
<p>In this system, five AI agents collaborate to create optimized content:</p>
<ul>
<li><p><strong>Research and Fact Checker:</strong> Conducts research to find trends and data.</p>
</li>
<li><p><strong>Audience Specialist:</strong> Analyzes audience needs for better engagement.</p>
</li>
<li><p><strong>Lead Content Writer:</strong> Writes engaging content based on research.</p>
</li>
<li><p><strong>Senior Editorial Director:</strong> Ensures content quality and consistency.</p>
</li>
<li><p><strong>SEO Specialist:</strong> Optimizes content for search engines.</p>
</li>
</ul>
<p>Using the OpenAI API, it employs chatGPT with crewAI to have these agents work for me.</p>
<h3 id="heading-before-ai-control-theory-as-the-first-ai">Before AI: Control Theory as the “First AI”</h3>
<p>Before symbolic and non symbolic AI, electrical engineering had data-driven methods. One key area that I’ve already mentioned above was control theory (which studies control systems for machines like cars and rockets). This field allows us to design systems that ensure stability despite disturbances and achieve goals beyond human capabilities.</p>
<p>Nowadays, after creating a control theory algorithm, we check if AI can improve the control system. In my experience, only some advanced deep learning methods are effective. Most machine learning methods don't outperform control theory in efficiency and security.</p>
<p>Control theory also offers better interpretability, allowing us to understand decisions, unlike advanced machine learning and deep learning.</p>
<p>Due to the historical importance of control theory, I will continue to mention its role and mathematical applications. This will help you learn AI's math foundations and understand its significance in electronic systems and AI applications in engineering beyond dataset predictions.</p>
<h2 id="heading-chapter-4-linear-algebra-the-geometry-of-data">Chapter 4: Linear Algebra - The Geometry of Data</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765002362611/905a356e-7686-4212-94ac-2b4a5b359c8a.jpeg" alt="Magnifying glass pointing at a book" style="display:block;margin:0 auto" width="4272" height="2848" loading="lazy">

<p>Photo by <a href="https://www.pexels.com/photo/monochrome-photo-of-math-formulas-3729557/">Nothing Ahead</a>.</p>
<p>Linear algebra is like having organized containers for data.</p>
<p>Instead of playing with individual numbers, we can pack them into structured boxes that are easier to handle. These structured boxes are called matrices.</p>
<p>When you have a lot of variables like customer data, sensor readings, or images, these structured boxes are very helpful. Also, what we can do when we play around with these boxes is very valuable.</p>
<p>In AI, linear algebra is everywhere. Take matrices, for example – a key concept in Linear Algebra. LLMs perform many matrix multiplications as their core operation. The data that they take in is also organized into matrices. In image recognition, matrices are used to represent pixels of images.</p>
<p>So as you can see, this core Linear Algebra concept is important to understand. Let's start!</p>
<h3 id="heading-what-are-matrices-and-why-do-they-simplify-equations">What Are Matrices and Why Do They Simplify Equations?</h3>
<p>Very often, systems in the real world can be simplified and modeled with a system of equations.</p>
<p>Those equations are often differential equations of many orders. But to simplify, let’s choose a very simple system like the one below:</p>
<p>$$\begin{align} 2x + 3y - z &amp;= 7 \ x - 2y + 4z &amp;= -1 \ 3x + y + 2z &amp;= 10 \end{align}$$</p>
<p>When dealing with many variables and equations, writing each equation separately quickly becomes frustrating. Matrices provide a compact way to represent these systems.</p>
<p>For example, here’s the system above as a single matrix equation:</p>
<p>$$\begin{bmatrix} 2 &amp; 3 &amp; -1 \ 1 &amp; -2 &amp; 4 \ 3 &amp; 1 &amp; 2 \end{bmatrix} \begin{bmatrix} x \ y \ z \end{bmatrix} = \begin{bmatrix} 7 \ -1 \ 10 \end{bmatrix}$$</p>
<p>By seeing systems of equations as matrices, we can use linear algebra techniques to understand how the system behaves.</p>
<p>Some of these techniques are:</p>
<ul>
<li><p>Linear Independence, Dependence, and Rank</p>
</li>
<li><p>Determinants</p>
</li>
<li><p>Eigenvalues and Eigenvectors</p>
</li>
</ul>
<p>So to summarize:</p>
<ol>
<li><p>A real world system can be represented as a system of equations</p>
</li>
<li><p>A system of equations can be compressed in a structured manipulable form called a matrix.</p>
</li>
<li><p>With matrices and linear algebra techniques, we can understand how the system works.</p>
</li>
</ol>
<p>This way, we can study the basic behavior of a system with Linear Algebra.</p>
<p>For complex systems like a rocket, Linear Algebra is still the foundation. More advanced tools from control theory are used, but understanding simpler systems is essential for modeling and creating complex ones.</p>
<h3 id="heading-vectors-and-transformations-moving-in-multiple-directions">Vectors and Transformations: Moving in Multiple Directions</h3>
<p>Vectors are matrices <strong>with a single row or a single column.</strong> You can also think of them as the building blocks of AI. They represent things like data points, model parameters, and much more.</p>
<p>For example, every data input (like an image or sentence) becomes a vector that the model can processes.</p>
<p>Here are two examples of vectors:</p>
<p>$$\mathbf{A} = \begin{bmatrix} 4 &amp; -2 &amp; 7 &amp; 1 &amp; 5 \end{bmatrix}$$</p>
<p>And:</p>
<p>$$\mathbf{B} = \begin{bmatrix} 3 \ -1 \ 8 \ 0 \ -4 \end{bmatrix}$$</p>
<p>All operations that you can perform on matrices can also be performed on vectors.</p>
<p>In Python, we can represent this by:</p>
<pre><code class="language-plaintext">import numpy as np

# Define vectors A and B
A = np.array([4, -2, 7, 1, 5])
B = np.array([3, -1, 8, 0, -4])
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756171163870/4fa7dc5d-5b68-4baf-a211-3db0c3915781.png" alt="Python code image representing the code above. Defining two NumPy arrays." style="display:block;margin:0 auto" width="2080" height="844" loading="lazy">

<p>We’re using the <a href="https://numpy.org/">NumPy</a> library because it makes math with arrays easy and fast.</p>
<p>As a simplification of a system of equations, a vector with a single row represents:</p>
<p>$$\mathbf{A} = \begin{bmatrix} 4 &amp; -2 &amp; 7 &amp; 1 &amp; 5 \end{bmatrix}$$</p>
<p>And this represents this system of equations:</p>
<p>$$4x_1 - 2x_2 + 7x_3 + x_4 + 5x_5 = k$$</p>
<p>A vector with a single column represents:</p>
<p>$$\mathbf{B} = \begin{bmatrix} 3 \ -1 \ 8 \ 0 \ -4 \end{bmatrix}$$</p>
<p>Which represents this system of equations:</p>
<p>$$\begin{align} x_1 &amp;= 3 \ x_2 &amp;= -1 \ x_3 &amp;= 8 \ x_4 &amp;= 0 \ x_5 &amp;= -4 \end{align}$$</p>
<p>Now let’s see some matrix operations.</p>
<p>For example:</p>
<p>$$\mathbf{A} + \mathbf{B}^T = \begin{bmatrix} 4 &amp; -2 &amp; 7 &amp; 1 &amp; 5 \end{bmatrix} + \begin{bmatrix} 3 &amp; -1 &amp; 8 &amp; 0 &amp; -4 \end{bmatrix} = \begin{bmatrix} 7 &amp; -3 &amp; 15 &amp; 1 &amp; 1 \end{bmatrix}$$</p>
<pre><code class="language-plaintext">vector_addition = A + B
print("A + B =", vector_addition)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756171174149/62309c55-a5c5-4f69-aef6-e8ab341b5926.png" alt="Python code image representing the code above. Adding two NumPy arrays." style="display:block;margin:0 auto" width="2080" height="572" loading="lazy">

<p>Which gives the result of the equation above.</p>
<p>Often, vector addition is used to combine features. For example, adding many user preference vectors creates a profile of a user.</p>
<p>Here’s a <strong>scalar multiplication:</strong></p>
<p>$$3\mathbf{A} = 3\begin{bmatrix} 4 &amp; -2 &amp; 7 &amp; 1 &amp; 5 \end{bmatrix} = \begin{bmatrix} 12 &amp; -6 &amp; 21 &amp; 3 &amp; 15 \end{bmatrix}$$</p>
<pre><code class="language-plaintext">scalar_mult = 3 * A
print("3 * A =", scalar_mult)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756171180976/17e260a4-baab-4866-ba30-fc12e090b87a.png" alt="Python code image representing the code above. Multiplying a NumPy array with a scalar." style="display:block;margin:0 auto" width="2080" height="572" loading="lazy">

<p>Which gives the result of the equation above.</p>
<p>In AI, scaling vectors is usually done to adjust relevancy. For example, if we do a scalar product multiplication of a vector by 100, it means we are increasing its value. If it is by 0.3, it means we are reducing its importance.</p>
<p>Here's an outer product multiplication:</p>
<p>$$\mathbf{A} \otimes \mathbf{B} = \begin{bmatrix} 4 \ -2 \ 7 \ 1 \ 5 \end{bmatrix} \times \begin{bmatrix} 3 &amp; -1 &amp; 8 &amp; 0 &amp; -4 \end{bmatrix} = \begin{bmatrix} 12 &amp; -4 &amp; 32 &amp; 0 &amp; -20 \ -6 &amp; 2 &amp; -16 &amp; 0 &amp; 8 \ 21 &amp; -7 &amp; 56 &amp; 0 &amp; -28 \ 3 &amp; -1 &amp; 8 &amp; 0 &amp; -4 \ 15 &amp; -5 &amp; 40 &amp; 0 &amp; -20 \end{bmatrix}$$</p>
<p>And here’s a <strong>dot product multiplication</strong> (also called a <strong>dot product</strong>):</p>
<p>$$\mathbf{A} \cdot \mathbf{B}^T = \begin{bmatrix} 4 &amp; -2 &amp; 7 &amp; 1 &amp; 5 \end{bmatrix} \cdot \begin{bmatrix} 3 &amp; -1 &amp; 8 &amp; 0 &amp; -4 \end{bmatrix}$$</p>
<p>$$= 4 \cdot 3 + (-2) \cdot (-1) + 7 \cdot 8 + 1 \cdot 0 + 5 \cdot (-4) = 50$$</p>
<p>We mainly use dot products when we want to measure similarity, or alignment between two vectors.</p>
<p>In machine learning, in one simple phrase, it gives us a measure of similarity.</p>
<pre><code class="language-plaintext">import numpy as np

dot_product = np.dot(A, B)
print("A · B =", dot_product)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756171200508/ee7b9e61-c1cb-497d-b038-b6a672c6d24b.png" alt="Python code image representing the code above. Multiplying a NumPy array via dot product." style="display:block;margin:0 auto" width="2080" height="752" loading="lazy">

<p>Which gives the result of the equation above.</p>
<h3 id="heading-linear-independence-dependence-and-rank-why-it-matters">Linear Independence, Dependence, and Rank: Why It Matters</h3>
<p>A lot of times, matrices can be made smaller and simpler. So it’s a good practice to reduce a matrix to its simplest form before we start to analyze its properties.</p>
<p>When each row of a matrix can be made with other rows, then that matrix is linearly dependent. This means the matrix can be further modified.</p>
<p>This way, a matrix&nbsp; has the property of linear independence when its rows cannot be created by combining each other.</p>
<p>For example, when we have a complex matrix like this one:</p>
<p>$$C = \begin{bmatrix} 1 &amp; 2 &amp; 3 &amp; 4 \ 2 &amp; 4 &amp; 6 &amp; 8 \ 1 &amp; 3 &amp; 5 &amp; 7 \ 0 &amp; 1 &amp; 2 &amp; 3 \end{bmatrix}$$</p>
<p>We can, with calculations, convert to this:</p>
<p>$$C_{\text{reduced}} = \begin{bmatrix} 1 &amp; 0 &amp; -1 &amp; -2 \ 0 &amp; 1 &amp; 2 &amp; 3 \ 0 &amp; 0 &amp; 0 &amp; 0 \ 0 &amp; 0 &amp; 0 &amp; 0 \end{bmatrix}$$</p>
<p>if you are not familiar with row reduction, I recommend <a href="https://www.youtube.com/watch?v=eDb6iugi6Uk">this YouTube video</a>.</p>
<p>The above simplified matrix is the same thing as this:</p>
<p>$$C_{\text{reduced}} = \begin{bmatrix} 1 &amp; 0 &amp; -1 &amp; -2 \ 0 &amp; 1 &amp; 2 &amp; 3 \end{bmatrix}$$</p>
<p>This way, we conclude that the C matrix has a <strong>rank</strong> of 2.</p>
<p>In other words, since the simplest form of the matrix has only 2 rows with numbers, it has a rank of 2.</p>
<p>From this, we can conclude that the reduced version of the matrix is <strong>linearly independent</strong>. This is because no row or column can be made from the existing rows or column. It’s the simplest possible matrix.</p>
<p>The original matrix C is linearly dependent because some rows are just multiples or combinations of other rows. For example, row 2 of the original matrix C is exactly row 1 multiplied by 2.</p>
<p>Another way of seeing this is that we have 4 rows in the original matrix and the rank of matrix C is 2. Since they are not equal, C is linearly dependent.</p>
<h4 id="heading-why-are-these-concepts-important">Why are these concepts important?</h4>
<p>Linear independence and rank are important in engineering because they show whether equations, represented as matrices, give unique information. In electrical circuits and control systems, knowing that equations, represented as matrices, are independent ensures that you have unique solutions and avoids confusion.</p>
<p>The matrix rank shows the maximum number of independent equations that can exist. This help engineers model the simplest possible form of the systems.</p>
<p>In LLMs like ChatGPT, Gemini, Grok, and Claude, linear independence, dependence, and rank are used in a very important technique called LoRA (Low-Rank Adaptation).</p>
<p>LoRA (Low-Rank Adaptation) is widely used to calibrate these models to make sure they adapt efficiently to new tasks or domains without retraining the full model. Also, there are variants of this technique, like Quantized LoRA. This way, in many data centers, LoRA saves energy, water for cooling, and so many other things.</p>
<h3 id="heading-determinants-measuring-space-and-scaling">Determinants: Measuring Space and Scaling</h3>
<p>Why are determinants important?</p>
<p>Determinants tell us if a system of equations has infinite solutions, no solutions, or if it has a unique solution without having to solve the whole system.</p>
<p>This way, instead of immediately trying to solve a complex system, we can first use the determinant to find out if it is even worth solving in the first place.</p>
<p>Many engineers don’t really understand the importance of the determinant. The only thing they know is the formula and how to apply it.</p>
<p>So now let’s learn, with some examples, what exactly the determinant is and why it matters.</p>
<p>A determinant is just a number. It’s always calculated from a square matrix. By calculating the determinant, we can find certain properties about the system it represents.</p>
<p>The determinant of a given matrix A:</p>
<p>$$A = \begin{bmatrix} a &amp; b \ c &amp; d \end{bmatrix}.$$</p>
<p>can be represented by two notations:</p>
<p>$$\det(A) = ad - bc$$</p>
<p>or</p>
<p>$$|A| = ad - bc$$</p>
<p>Both are the same thing.</p>
<p>Let's see how to calculate a determinant:</p>
<p>$$|A| = \begin{vmatrix} 2 &amp; 3 \ 1 &amp; 4 \end{vmatrix} = (2)(4) - (3)(1) = 8 - 3 = 5.$$</p>
<p>Let’s see how to do this in Python:</p>
<pre><code class="language-plaintext">import numpy as np

# Define the matrix
A = np.array([
    [2, 3],
    [1, 4]
])

# Calculate the determinant
det_A = np.linalg.det(A)

print("Determinant of A:", det_A)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756233259727/feea57a3-5a33-49b9-a74a-979eba5ec7fe.png" alt="Python code image representing the code above. Finding the determinant." style="display:block;margin:0 auto" width="2080" height="1472" loading="lazy">

<h4 id="heading-the-same-calculation-works-for-other-matrices">The same calculation works for other matrices!</h4>
<p>Here's the determinant formula for a 3×3 matrix:</p>
<p>For a 3 by 3 matrix:</p>
<p>$$|B|= \begin{vmatrix} a &amp; b &amp; c \ d &amp; e &amp; f \ g &amp; h &amp; i \end{vmatrix} = aei + bfg + cdh - ceg - bdi - afh.$$</p>
<p>Now let’s apply the formula to an example:</p>
<p>$$|B| = \begin{vmatrix} 1 &amp; 2 &amp; 3 \ 0 &amp; 4 &amp; 5 \ 1 &amp; 0 &amp; 6 \end{vmatrix} = (1)(4)(6) + (2)(5)(1) + (3)(0)(0) - (3)(4)(1) - (2)(0)(6) - (1)(5)(0)$$</p>
<p>Assessing each term:</p>
<p>$$= (1)(4)(6) + (2)(5)(1) - (3)(4)(1) = 4 \cdot 6 + 2 \cdot 5 - ( 3 \cdot 4) = 24+10-12 = 22$$</p>
<p>In Python code:</p>
<pre><code class="language-plaintext">import numpy as np

# Define the matrix
B = np.array([
    [1, 2, 3],
    [0, 4, 5],
    [1, 0, 6]
])

# Calculate the determinant
det_B = np.linalg.det(B)

print("Determinant of B:", det_B)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756233606615/4e333b35-4714-480a-8a3b-62db799614e1.png" alt="Python code image representing the code above. Finding a 3 by 3 determinant." style="display:block;margin:0 auto" width="2080" height="1564" loading="lazy">

<p>Now, let’s visualize matrix A by plotting its column vectors. Each column will become a vector: (3,1) and (-2,4). This shows us geometrically what the matrix is actually doing.</p>
<p>In a geogebra graph, it gives us this:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756235393476/6b5c38ea-7b27-4e3d-8ad4-346417d35e77.png" alt="Representation of 2 vectors in a Cartesian plane." style="display:block;margin:0 auto" width="1320" height="1003" loading="lazy">

<p>As we can see, the vectors define how each variable influences the system. By visualizing what the matrices are doing, we can find patterns that are harder to find just by looking at formulas.</p>
<p><strong>What does this mean visually?</strong></p>
<p>It means that in the space, this is what our matrix looks like. It’s also how our system of equations is represented.</p>
<p>C1 represents the “force“ or the impact the variable x1 has. And C2 does the same thing for the variable x2.</p>
<p>Now we’ll focus on a 3D matrix example. This matrix D represents a system of three equations with three variables:</p>
<p>$$D = \begin{bmatrix} 2 &amp; -1 &amp; 3 \ 4 &amp; 0 &amp; -2 \ -1 &amp; 5 &amp; 1 \end{bmatrix}$$</p>
<p>$$\begin{align} 2x_1 - x_2 + 3x_3 &amp;= p \ 4x_1 + 0x_2 - 2x_3 &amp;= q \ -x_1 + 5x_2 + x_3 &amp;= r \end{align}$$</p>
<p>Each column can be described as a separate vector:</p>
<p>$$\begin{equation} D = \left[ D_1 \mid D_2 \mid D_3 \right] = \left[ \begin{bmatrix} 2 \ 4 \ -1 \end{bmatrix} \mid \begin{bmatrix} -1 \ 0 \ 5 \end{bmatrix} \mid \begin{bmatrix} 3 \ -2 \ 1 \end{bmatrix} \right] \end{equation}$$</p>
<p>As we can see, D was decomposed in 3 new column vectors:</p>
<p>$$\begin{equation} D_1 = \begin{bmatrix} 2 \ 4 \ -1 \end{bmatrix} \end{equation}$$</p>
<p>and:</p>
<p>$$\begin{equation} D_2 = \begin{bmatrix} -1 \ 0 \ 5 \end{bmatrix} \end{equation}$$</p>
<p>and:</p>
<p>$$\begin{equation} D_3 = \begin{bmatrix} 3 \ -2 \ 1 \end{bmatrix} \end{equation}$$</p>
<p>In a geogebra graph, it gives us this:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756236913078/8d8a3d48-20a9-423b-bfb8-4368d92ec340.png" alt="Representation of 3 vectors in a 3D Cartesian plane." style="display:block;margin:0 auto" width="1525" height="1141" loading="lazy">

<p>In 3D, each vector points in its own direction. Together, they organize three planes. Where all three planes touch is the solution to the system.</p>
<p>This is a key advantage of matrices and linear algebra. They help us visualize both simple and complex systems, enhancing systems thinking and first principles thinking.</p>
<p>The determinant is directly connected to these visualizations. For example, in 2D it measures the area that the vectors stretch over. Now we’ll see how that’s possible.</p>
<p>Let's use matrix A and see what its determinant looks like in geometric terms:</p>
<p>$$A = \begin{bmatrix} 2 &amp; 3 \ 1 &amp; 4 \end{bmatrix}$$</p>
<p>Which can be decomposed into 2 vectors <code>u</code> and <code>v</code>:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756241016899/ded47498-b030-4fa1-a4fe-07153d138a7f.png" alt="Representation of 2 vectors (matrix A) in a Cartesian plane." style="display:block;margin:0 auto" width="859" height="835" loading="lazy">

<p>It gives us this determinant:</p>
<p>$$|A| = \begin{vmatrix} 2 &amp; 3 \ 1 &amp; 4 \end{vmatrix} = (2)(4) - (3)(1) = 8 - 3 = 5.$$</p>
<p>Now let’s see the determinant visually.</p>
<p>From (2,1) and (3,4), we can draw vectors parallel to u and and v. These are called u' and v' and have the same magnitude. They meet at (5,5), and we have a parallelogram that’s completed with these points: (0,0),(2,1),(3,4),(5,5)</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756241586617/d825b8e2-d839-4b15-bdd0-d9b5efd80942.png" alt="Representation of the 4 vectors being used in the determinant" style="display:block;margin:0 auto" width="1063" height="1048" loading="lazy">

<p>The area of the parallelogram is the determinant:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756241692073/deb2e0cd-32a3-4a1a-90e7-e556f5039169.png" alt="Illustrating that the area limited by the 4 vectors is the determinant." style="display:block;margin:0 auto" width="1062" height="976" loading="lazy">

<p>Let’s see another example.</p>
<p>Let’s use a matrix F and see what it truly is:</p>
<p>$$F = \begin{bmatrix} 1 &amp; 2 \ 2 &amp; 4 \end{bmatrix}$$</p>
<p>It gives us this determinant:</p>
<p>$$|F| = \begin{vmatrix} 1 &amp; 2 \ 2 &amp; 4 \end{vmatrix} = (1)(4) - (2)(2) = 4 - 4 = 0$$</p>
<p>In geogebra, we can see that:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756242215981/d88f2e80-04ba-46b9-979d-d7684f161210.png" alt="Representation of the 2 vectors being used in the determinant" style="display:block;margin:0 auto" width="778" height="1072" loading="lazy">

<p>Now let’s try to see the determinant visually:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756242340382/46551578-69a5-4ef9-ab86-9149e7fb4aaa.png" alt="Illustrating that the area limited by the 2 vectors is the determinant and that it does not exist. So the determinant is zero." style="display:block;margin:0 auto" width="721" height="991" loading="lazy">

<p>We can conclude that the area is 0.</p>
<p>Now let’s use a matrix G and see what it truly is:</p>
<p>$$G = \begin{bmatrix} 1 &amp; 5 \ 2 &amp; 3 \end{bmatrix}$$</p>
<p>It gives us this determinant:</p>
<p>$$|G| = \begin{vmatrix} 1 &amp; 5 \ 2 &amp; 3 \end{vmatrix} = (1)(3) - (5)(2) = 3 - 10 = -7$$</p>
<p>In geogebra, we can see that:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756242987960/d182b725-81ba-4042-81e1-6b0232e09ffb.png" alt="Representation of the 2 vectors being used to find the determinant" style="display:block;margin:0 auto" width="1411" height="976" loading="lazy">

<p>Now let’s try to see the determinant visually.</p>
<p>From (1,2) and (5,3), we can draw vectors parallel to u and and v. These are called u' and v' and have the same magnitude. They meet at (6,5). A parallelogram is completed with these points: (0,0),(1,2),(5,3),(6,5)</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756243098714/881693d4-7a84-4b72-bb87-3fb48b25fe4b.png" alt="Representation of 4 vectors being used to find the determinant before showing the area" style="display:block;margin:0 auto" width="1201" height="1030" loading="lazy">

<p>Again, the area of the parallelogram is the determinant:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756243316071/ce8fa65b-6370-4ada-9fe6-cdf20ab4546d.png" alt="Illustrating that the area limited by the 4 vectors is the determinant." style="display:block;margin:0 auto" width="1167" height="1023" loading="lazy">

<p>We just saw that the determinant is the area of a parallelogram formed by the vectors. When the determinant is 0, there is no area. In other cases, there is an area. But what does this mean, and why do we care about these different values?</p>
<p><strong>When the det = 0:</strong></p>
<ul>
<li><p>The vectors are linearly dependent (one can be written as a combination of the others)</p>
</li>
<li><p>They lie on the same line or one is a scaled version of the other</p>
</li>
<li><p>The parallelogram collapses to a line, hence zero area</p>
</li>
<li><p>This tells us the matrix has no inverse</p>
</li>
<li><p><strong>Systems of equations either have no solution or infinitely many solutions</strong></p>
</li>
</ul>
<p><strong>When the det ≠ 0 (det &gt; 0 or det &lt; 0):</strong></p>
<ul>
<li><p>The vectors form a proper parallelogram with an area</p>
<ul>
<li><p>If det &gt; 0, the area is positive and transformation preserves orientation</p>
</li>
<li><p>If det &lt; 0, the area is negative and the orientation is flipped</p>
</li>
</ul>
</li>
<li><p>The vectors are linearly independent</p>
</li>
<li><p><strong>Systems of equations have exactly one solution</strong></p>
</li>
</ul>
<p>In electrical engineering, determinants help verify if a control system is controllable and observable.</p>
<p>Control systems use matrices a lot. For this reason, checking if their determinants are zero or non-zero tells engineers:</p>
<ul>
<li><p>If it is controllable, it means the system is reachable, which helps in stabilization and performance optimization.</p>
</li>
<li><p>If it is observable, it means the system is measurable, which helps in fault detection and system monitoring.</p>
</li>
</ul>
<p>In finite element analysis, a very popular math tool to solve partial differential equations, determinants helps figure out quickly if the calculations will give reliable results.</p>
<p>This way, with finite element analysis, we can design safer buildings, optimize aircraft wings, and simulate medical implants – all of which have a large impact on human lives and safety.</p>
<p>In machine learning, determinants are crucial to understanding data transformations. In these methods, if a determinant with a value of zero shows up, it means you are losing information and can't recover original data.</p>
<p>Also in deep learning, it’s used to decide the first parameters of neural networks (weight initialization) to prevent problems like the vanishing/exploding gradients.</p>
<p>In a 3×3 matrix, the determinant represents the volume of a parallelepiped (a 3D "box") formed by three vectors in 3D space.</p>
<ul>
<li><p>If det = 0: The three vectors lie in the same plane, so they don't span any 3D volume</p>
</li>
<li><p>If det ≠ 0: The vectors form a proper 3D shape with actual volume</p>
</li>
</ul>
<p>The absolute value |det| gives you the exact volume of that <a href="https://en.wikipedia.org/wiki/Parallelepiped">parallelepiped</a>.</p>
<p>For example, if you have vectors a, b, and c, the determinant tells you how much 3D space they "fill up" when you use them as the edges of a box.</p>
<p>This is where it gets fascinating:</p>
<ul>
<li><p>4×4 matrix: The determinant represents the "hypervolume" of a 4D parallelepiped formed by four vectors in 4-dimensional space.</p>
</li>
<li><p>1000×1000 matrix: The determinant represents the hypervolume in 1000-dimensional space!</p>
</li>
</ul>
<p>So, to summarize, the determinant tells us easily if there are no solutions, infinite solutions, or exactly one solution in a system of equations, represented by a compact matrix.</p>
<h3 id="heading-what-are-mathematical-spaces-and-how-do-they-simplify-calculations">What Are Mathematical Spaces and How Do They Simplify Calculations?</h3>
<p>We now have a great foundation to understand the rest of this chapter on linear algebra.</p>
<p>Now, we will see see how a linearly independent matrix create something called a basis. Also, we will see that a basis is just a a set of building blocks for mathematical spaces!</p>
<p>The row vectors of a linearly independent matrix form a basis.</p>
<p>For example in matrix A, which is linearly independent:</p>
<p>$$A = \begin{bmatrix} 1 &amp; 0 &amp; 0 &amp; 0 \ 0 &amp; 1 &amp; 0 &amp; 0 \ 0 &amp; 0 &amp; 1 &amp; 0 \ 0 &amp; 0 &amp; 0 &amp; 1 \end{bmatrix}$$</p>
<p>forms this set:</p>
<p>$$((1,0,0,0), (0,1,0,0), (0,0,1,0), (0,0,0,1))$$</p>
<p>In this case, since matrix A is linearly independent, the set of matrix rows is called a <strong>basis</strong>. From this basis, you can create endless linear combinations of any other vector. The collection of all these possible combinations is called a <strong>mathematical space</strong>.</p>
<p>A mathematical space is an infinite set where all linear combinations of a basis exist. Its called a basis because these vectors <strong>form the base</strong> to express any vector in the space as a linear combination.</p>
<p>This matrix B is linearly independent:</p>
<p>$$B = \begin{bmatrix} 1 &amp; 0 \ 0 &amp; 1 \ \end{bmatrix}$$</p>
<p>And forms this set:</p>
<p>$$((1, 0), (0, 1))$$</p>
<p>And from this come all possible points in this cartesian coordinate system:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756247201687/a847b8c0-5678-431c-b446-e1897afdffc6.png" alt="Showing in the Cartesian plane where the point (2, 3) is" style="display:block;margin:0 auto" width="1084" height="1114" loading="lazy">

<p>For example, mathematically, we can get the point (2,3) by:</p>
<p>$$(x=2, y=3) = 2(1, 0) + 3(0, 1) = (2, 0) + (0, 3) = (2, 3)$$</p>
<p>Note: There are other bases for the cartesian coordinate plane. I chose this one because it’s the easiest to understand.</p>
<h3 id="heading-eigenvalues-and-eigenvectors-unlocking-hidden-patterns">Eigenvalues and Eigenvectors: Unlocking Hidden Patterns</h3>
<p>Eigenvalues and eigenvectors, in my opinion, are far simpler than what mathematics professors make them out to be at university:</p>
<ul>
<li><p>Eigenvalues tell you how much a matrix stretches or shrinks things.</p>
</li>
<li><p>Eigenvectors tell you which directions stay unchanged when the matrix transforms them.</p>
</li>
</ul>
<p>This way, a matrix may have one or many eigenvalues which in turn result in many eigenvectors.</p>
<p>Let’s see an example:</p>
<p>For a square matrix A, eigenvalue λ, and eigenvector v:</p>
<p>$$Av=λv$$</p>
<p>The easiest way to find the eigenvalue is to calculate this:</p>
<p>$$det(A−λI)=0$$</p>
<p>or:</p>
<p>$$|A−λI|=0$$</p>
<p>Again, we have different notations for the determinant, but they’re the same thing.</p>
<p>Anyway, let’s define a very simple matrix A:</p>
<p>$$A = \begin{bmatrix} 2 &amp; 0 \ 0 &amp; 3 \end{bmatrix}$$</p>
<p>Now let’s make some calculations.</p>
<p>This formula:</p>
<p>$$det(A−λI)=0$$</p>
<p>Can be decomposed into:</p>
<p>$$det(\begin{bmatrix} 2 &amp; 0 \ 0 &amp; 3 \end{bmatrix} - λ \times \begin{bmatrix} 1 &amp; 0 \ 0 &amp; 1 \end{bmatrix}) = 0$$</p>
<p>Which is the same has:</p>
<p>$$det(\begin{bmatrix} 2 &amp; 0 \ 0 &amp; 3 \end{bmatrix} - \begin{bmatrix} λ &amp; 0 \ 0 &amp; λ \end{bmatrix}) = 0$$</p>
<p>Which gives us:</p>
<p>$$det(\begin{bmatrix} 2-λ &amp; 0 \ 0 &amp; 3-λ \end{bmatrix}) = 0$$</p>
<p>By the calculations we made above on the determinant, we can conclude that:</p>
<p>$$(2-λ) \times (3-λ) = 0$$</p>
<p>Which is the same has:</p>
<p>$$2-\lambda = 0 \text{ or } 3-\lambda = 0$$</p>
<p>Which gives us these eigenvalues:</p>
<p>$$\lambda_1 = 2, \quad \lambda_2 = 3$$</p>
<p>And these eigenvectors:</p>
<p>$$\mathbf{v_1} = \begin{bmatrix} 1 \ 0 \end{bmatrix}, \quad \mathbf{v_2} = \begin{bmatrix} 0 \ 1 \end{bmatrix}$$</p>
<p>This means that in the Cartesian coordinate system:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756321668969/949a5a4b-12ff-4490-bbff-1cc032bc5705.png" alt="Showing how the eigenvectors are related to the vectors in matrix A visually. Both have the same directions but different scalar values." style="display:block;margin:0 auto" width="997" height="988" loading="lazy">

<p>By applying the eigenvectors, we can see that:</p>
<ul>
<li>The eigenvalue 2 is associated with the eigenvector v1:</li>
</ul>
<p>$$A\mathbf{v_1} = \begin{bmatrix} 2 &amp; 0 \ 0 &amp; 3 \end{bmatrix}\begin{bmatrix} 1 \ 0 \end{bmatrix} = \begin{bmatrix} 2 \ 0 \end{bmatrix} = 2\begin{bmatrix} 1 \ 0 \end{bmatrix}$$</p>
<ul>
<li>The eigenvalue 3 is associated with the eigenvector v2:</li>
</ul>
<p>$$A\mathbf{v_2} = \begin{bmatrix} 2 &amp; 0 \ 0 &amp; 3 \end{bmatrix}\begin{bmatrix} 0 \ 1 \end{bmatrix} = \begin{bmatrix} 0 \ 3 \end{bmatrix} = 3\begin{bmatrix} 0 \ 1 \end{bmatrix}$$</p>
<p>Here is the Python code to calculate this:</p>
<pre><code class="language-plaintext">import numpy as np

# Define matrix A
A = np.array([[2, 0],
              [0, 3]])

# Calculate eigenvalues and eigenvectors
eigenvalues, eigenvectors = np.linalg.eig(A)

print("Eigenvalues:")
print(eigenvalues)

print("Eigenvectors (columns):")
print(eigenvectors)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756322044095/bc76f0ec-1d13-4845-b0f3-2847118860a3.png" alt="Python code, with NumPy array, showing how to find the eigenvalues" style="display:block;margin:0 auto" width="2080" height="1744" loading="lazy">

<p>Eigenvalues and eigenvectors are key tools in engineering and machine learning because they reveal a matrix's fundamental behavior. Although a matrix transformation might seem complex, in reality:</p>
<ul>
<li><p>Eigenvalues show how much stretching or compression occur.</p>
</li>
<li><p>Eigenvectors identify the special directions where this stretching happens most naturally.</p>
</li>
</ul>
<p>In machine learning, we can use Principal Component Analysis (PCA) to make datasets smaller.</p>
<p>So, for example, let's say you’re building a machine learning application to predict heart disease. You have 100 data categories and 1 target variable telling whether a person has it or not.</p>
<p>With PCA, you can convert the 100 categories into, say, 40 categories. This way, you can make a smaller machine learning model and save computational resources.</p>
<p>PCA uses eigenvectors of covariance matrices to find important directions in data with many variables. It reduces data size without losing much detail, helping machine learning algorithms focus on key features and ignore unnecessary information.</p>
<h3 id="heading-applications-of-linear-algebra-in-ai-and-control-theory">Applications of Linear Algebra in AI and Control Theory</h3>
<p>‌Linear algebra serves as the mathematical foundation for all engineering fields.</p>
<p>In addition, the principles of matrices and linear transformations provide the computational foundation that makes modern AI possible while enabling the control of complex systems.</p>
<p>All LLMs, from ChatGPT and Claude to Gemini and Grok, rely on linear operations.</p>
<p>All these systems carry out huge matrix multiplications to handle and create human language. So, when you type something into ChatGPT, probably millions of matrix multiplications are happening as you wait for a response!</p>
<p>In control theory, especially in an area called state-space control theory, matrices make it possible to create complex controllers. Linear algebra helps engineers design controllers for things like aircraft autopilots and robotic systems, among other applications</p>
<p>For example, when a rocket adjusts its trajectory or a drone maintains stable flight, many matrix multiplications are happening to determine the best way to guarantee the system’s stability.</p>
<p>Thanks to GPUs, linear algebra matrices are very efficient to compute. Also, any new matrix multiplication algorithms or special hardware for faster linear operations can greatly enhance AI and control systems.</p>
<p>In the end, linear algebra is the hidden mathematical engine powering the current AI revolution.</p>
<h2 id="heading-chapter-5-multivariable-calculus-change-in-many-directions">Chapter 5: Multivariable Calculus -&nbsp;Change in Many Directions</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765002238157/a377cdc6-7e85-491b-90b8-8b3243618288.jpeg" alt="Photo of a women writing a calculus equation in a board" style="display:block;margin:0 auto" width="7804" height="5205" loading="lazy">

<p><a href="https://www.pexels.com/photo/woman-writing-on-a-whiteboard-3862130/">Photo by ThisIsEngineering</a></p>
<h3 id="heading-limits-and-continuity-understanding-smooth-change">Limits and Continuity: Understanding Smooth Change</h3>
<p>Calculus is one of the most valuable areas of mathematics and it focus on the study of continuous change.</p>
<p>Before we start learning a topic that makes many people give up on engineering degrees, I want to once again assure you that this chapter is very easily explained with a lot of images and code examples.</p>
<p>Also, just like linear algebra, many concepts in calculus are components of tools that have helped create billion-dollar industries.</p>
<h4 id="heading-what-is-continuity">What is continuity?</h4>
<p>Before going and explaining topics like derivatives and integrals, we need to understand continuity.</p>
<p>In simple terms, continuity means that a function has no breaks, jumps, or holes.</p>
<p>Essentially, you can draw it without lifting your pencil from the paper.</p>
<p>For example, this function is continuous:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756402257225/f9cfc4f3-a6f1-4fb9-9ed1-f690c4ffffc4.png" alt="Example of a function that is continuous" style="display:block;margin:0 auto" width="634" height="901" loading="lazy">

<p>You can draw this graph without taking the pencil off the paper.</p>
<p>The above graph is represented by this function:</p>
<p>$$y = x^2 - 4x + 3$$</p>
<p>But the below function is <strong>not</strong> continuous:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756402337970/b5a65748-572d-4342-9685-9472babde38a.png" alt="Example of a function that is not continuous" style="display:block;margin:0 auto" width="1315" height="1084" loading="lazy">

<p>This one, you <strong>can’t</strong> draw without taking the pencil off the paper.</p>
<p>It’s represented by this piecewise function:</p>
<p>$$y = \begin{cases} 1.5 + \frac{1}{x+1} &amp; \text{if } -1 &lt; x &lt; 2 \ 2 + \frac{2}{(x-1)^2} &amp; \text{if } x &gt; 2 \end{cases}$$</p>
<p>This piecewise function is essentially two individual functions for two different intervals of numbers. Since calculus is the study of continuous change, we can only realistically use it in continuous functions.</p>
<h4 id="heading-how-do-limits-guarantee-continuity">How do limits guarantee continuity?</h4>
<p>We can only use tools like derivatives and integrals if a function is continuous.</p>
<p>How can we describe mathematically that a function is continuous – like drawing it without lifting our pencil from the paper?</p>
<p>Limits solve that problem.</p>
<p>When we take the limit of a function at a given point, we're asking: what value does a function approach as we get close to that point?</p>
<p>Let's look at some examples of this function at these points and also understand the notation used in limits:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756403511442/de3450f2-dcf9-40e3-a04e-846334abeebd.png" alt="Example of a function that is continuous and its various points" style="display:block;margin:0 auto" width="759" height="1104" loading="lazy">

<ol>
<li><strong>What is the limit of the point x=0?</strong></li>
</ol>
<p>It is 3. It actually crosses the y axis.</p>
<p>In mathematical notation,</p>
<p>$$\begin{align} \lim_{x \to 0} (x^2 - 4x + 3) &amp;= (0)^2 - 4(0) + 3 \ &amp;= 0 - 0 + 3 \ &amp;= 3 \end{align}$$</p>
<p>In this notation, we're asking what the value of the y function is as x gets very close to 0. Think of x as being at 0.00000000000001 or -0.00000000000001. It gets so close that we can consider it near enough.</p>
<ol>
<li><strong>What is the limit of the point x=1?</strong></li>
</ol>
<p>Le’s see another example:</p>
<p>In this case, it’s 0.</p>
<p>$$\begin{align} \lim_{x \to 1} (x^2 - 4x + 3) &amp;= (1)^2 - 4(1) + 3 \ &amp;= 1 - 4 + 3 \ &amp;= 0 \end{align}$$</p>
<p>In this notation, we're asking what the value of the y function is as x gets very close to 1. Think of x as being at 0.99999999999999 or 1.00000000000001. It gets so close that we can consider it near enough.</p>
<ol>
<li><strong>What is the limit of the point x=2?</strong></li>
</ol>
<p>Le’s see another example</p>
<p>Here, it’s -1.</p>
<p>$$\begin{align} \lim_{x \to 2} (x^2 - 4x + 3) &amp;= (2)^2 - 4(2) + 3 \ &amp;= 4 - 8 + 3 \ &amp;= -1 \end{align}$$</p>
<p>Some more quick examples:</p>
<ol>
<li><strong>What is the limit of the point x=3?</strong></li>
</ol>
<p>In this notation, we're asking what the value of the y function is as x gets very close to 1. Think of x as being at 1.99999999999999 or 2.00000000000001. It gets so close that we can consider it near enough.</p>
<ol>
<li><strong>What is the limit of the point x=4?</strong></li>
</ol>
<p>It is 0.</p>
<ol>
<li><strong>What is the limit of the point x=5?</strong></li>
</ol>
<p>It is 3.</p>
<p>Now let’s see another example:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756403617161/b67b2977-8ae4-4c06-8156-d7c6a64ee2e1.png" alt="Example of a function that is not continuous at a point of x=2" style="display:block;margin:0 auto" width="1315" height="1084" loading="lazy">

<p>In the point x=2, it’s not well defined</p>
<ul>
<li><p>If we draw with a pencil from the left to x=2, we end up with 1.83333</p>
</li>
<li><p>If we draw with a pencil from the right to x=2, we end up with 4</p>
</li>
</ul>
<h3 id="heading-why-are-limits-important-to-understand-derivatives-and-integrals">Why are limits important to understand derivatives and integrals?</h3>
<p>As we have seen, when we talk about limits, we are talking about a value that symbolizes the value that a function approaches as it comes toward a particular point.</p>
<p>It’s critical to note that we're not looking at the value of that point itself. We’re looking at what happens as we get so near to it that we can pin down what value the function is approaching.</p>
<p>I will now show a very simple example to demonstrate this concept using mathematical notation.</p>
<p>I know that limits can be a difficult concept to understand at first. But if you understand limits very well, then you'll be well-prepared to understand derivatives and integrals.</p>
<p>And, as you’ll see, derivatives are responsible for modern AI and integrals are important parts of tolls widely used in billion-dollar industries.</p>
<p>I want you to understand the <strong>intuition</strong> behind this.</p>
<p>The function z(x) is continuous:</p>
<p>$$z(x) = \frac{3x + 7}{x + 2}$$</p>
<p><strong>So to what value does this expression converge as x approaches infinity?</strong></p>
<p>If you have a background in math, you might see why. But here for those who aren’t sure:</p>
<ul>
<li>It converges to 3.</li>
</ul>
<p>This time, the limit will be approaching infinity instead of a constant:</p>
<p>$$\begin{align} \lim_{x \to \infty} \frac{3x + 7}{x + 2} \end{align}$$</p>
<p>Let’s solve this in a very simple way:</p>
<ul>
<li>For x = 1:</li>
</ul>
<p>$$f(1) = \frac{3(1) + 7}{1 + 2} = \frac{10}{3} \approx 3.333...$$</p>
<ul>
<li>For x = 5:</li>
</ul>
<p>$$f(5) = \frac{3(5) + 7}{5 + 2} = \frac{22}{7} \approx 3.143...$$</p>
<ul>
<li>For x = 10:</li>
</ul>
<p>$$f(10) = \frac{3(10) + 7}{10 + 2} = \frac{37}{12} \approx 3.083...$$</p>
<ul>
<li>For x = 50:</li>
</ul>
<p>$$f(50) = \frac{3(50) + 7}{50 + 2} = \frac{157}{52} \approx 3.019...$$</p>
<ul>
<li>For x = 100:</li>
</ul>
<p>$$f(100) = \frac{3(100) + 7}{100 + 2} = \frac{307}{102} \approx 3.010...$$</p>
<ul>
<li>For x = 1000:</li>
</ul>
<p>$$f(1000) = \frac{3(1000) + 7}{1000 + 2} = \frac{3007}{1002} \approx 3.001...$$</p>
<ul>
<li>For x = 10000:</li>
</ul>
<p>$$f(10000) = \frac{3(10000) + 7}{10000 + 2} = \frac{30007}{10002} \approx 3.0001...$$</p>
<p>As x gets bigger and bigger, we get closer and closer to 3.</p>
<p>This is the main idea of limits: Describe the value a function approaches as the input approaches some point.</p>
<p>This same idea applies to derivatives: they’re just limits that measure rates of change (slopes of tangent lines).</p>
<p>And as well, Integrals are just limits that measure accumulated quantities (areas under curves)..</p>
<p>Let’s now see how derivatives work in depth.</p>
<h3 id="heading-derivatives-how-things-change-and-how-fast">Derivatives: How Things Change and How Fast</h3>
<p>As I said before, derivatives are just limits that measure rates of change (slopes of tangent lines).</p>
<p>But what does this actually mean?</p>
<p>Let’s see an example:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756755419750/75b36254-0f4a-4395-8dd4-14ac16399ff3.png" alt="Example of a function" style="display:block;margin:0 auto" width="1263" height="1005" loading="lazy">

<p><strong>What is the rate of change in the point A?</strong></p>
<p>Hard question right? Let’s think how to answer this with limits.</p>
<p>We can find the limit of the rate of change in point A(0.72, 0.66), also called the instantaneous rate of change.</p>
<p>Let’s do that:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756755680672/40f94361-55c7-4a9e-bfaf-b2b855fa0712.png" alt="Example of a function and choosing two points (B and C) to find the rate of change in point A" style="display:block;margin:0 auto" width="1437" height="957" loading="lazy">

<p>To find the slope, we take the coordinates of the points B(0.2, 0.2) and C(1.6, 1):</p>
<p>$$\text{slope} = \frac{1 - 0.2}{1.6 - 0.2} = \frac{0.8}{1.4} = \frac{4}{7} \approx 0.571$$</p>
<p>This gives us a rate of change:</p>
<p>$$y=0.571x + 0.084$$</p>
<p>Let's approximate more:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756756069833/3a4a1991-4983-4751-a68e-68bd6780300d.png" alt="Example of a function and choosing two points (B and C) to find the rate of change in point A. But B and C are closer to A." style="display:block;margin:0 auto" width="1492" height="1027" loading="lazy">

<p>Let’s also zoom in:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756756131072/f96b7f82-a4ed-4720-8c87-fd2936bae9d9.png" alt="Example of a function and choosing two points (B and C) to find the rate of change in point A. But B and C are closer to A, and we have to zoom in." style="display:block;margin:0 auto" width="1569" height="1134" loading="lazy">

<p>To find the slope, we use the coordinates of the points B(0.58, 0.55) and C(0.85, 0.75):</p>
<p>$$\text{slope} = \frac{0.85- 0.58}{0.75 - 0.55} = \frac{0.27}{0.2} = \frac{2.7}{2} \approx 1.35$$</p>
<p>It gives us a rate of change:</p>
<p>$$y=1.35x + 0.11$$</p>
<p>Now let's approximate a lot:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756756879223/11d26af3-06ec-4419-b631-10308b4cadef.png" alt="Example of a function and choosing two points (B and C) to find the rate of change in point A. But B and C are closer to A, and we have to zoom in." style="display:block;margin:0 auto" width="1513" height="1098" loading="lazy">

<p>To find the slope, we use the coordinates of the points B(0.7242549, 0.6625776) and C(0.7242884, 0.66260026):</p>
<p>$$\text{slope} = \frac{0.66260026- 0.6625776}{0.7242884- 0.7242549} = \frac{0.0000226}{0.0000335} = \frac{0.226}{0.335} \approx 0.674$$</p>
<p>Now let’s zoom out:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756757322888/a6f58b41-d6ff-44fd-b18f-06fb1f8f0e06.png" alt="Rate of change at point C" style="display:block;margin:0 auto" width="1195" height="907" loading="lazy">

<p>As we can see, we are so close that we can consider the limit of the rate of change to be 0.65.</p>
<p>It gives us the rate of change:</p>
<p>$$y=0.674x + 0.12$$</p>
<p><strong>This way, the limit of a rate of change is called a derivative.</strong></p>
<p>To recap, here is an animation:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756766733257/a1754b47-7c57-4387-8b4c-886ed7b8f80a.gif" alt="GIF animation based on previous images" style="display:block;margin:0 auto" width="1195" height="907" loading="lazy">

<p>Here’s a Python code example that lets you find the derivative in point A:</p>
<pre><code class="language-python">import sympy as sp

x = sp.symbols('x')
f = sp.sin(x)

# Derivative of sin(x)
derivative_of_sin = sp.diff(f, x)

# Evaluate at x = 0.72 and x = 0.66
val = f_prime.subs(x, 0.72).evalf()

print("Derivative of sin(x) at x=0.72:", val)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756758436107/3bda58c5-96d6-4834-a2ec-ab8fedc4cb56.png" alt="Image of code example to find the derivative of the function sin(x)" style="display:block;margin:0 auto" width="2080" height="1564" loading="lazy">

<p>The function that had the point A is called a sine wave.</p>
<p>We convert it to its derivative function. From there we have our rate of change at point 0.72.</p>
<p>When we do math by hand, <strong>we usually have many rules to convert a function to its derivative, and from these find the rate of change for a given point.</strong></p>
<p>Before seeing it, let’s look at a very simple example to understand the definition of a derivative:</p>
<p>$$\frac{d}{dx}f(x) \approx \frac{f(\textcolor{green}{x + h}) - f(\textcolor{red}{x - h})}{\textcolor{green}{x + h} - \textcolor{red}{x - h}} = \frac{f({x + h}) - f({x - h})}{2h}$$</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1756767749954/87486d8c-9437-460c-b556-e9333b1590c5.png" alt="Image showing in derivative definition how each component is related visually to a line representing the rate of change" style="display:block;margin:0 auto" width="1513" height="1098" loading="lazy">

<p><code>h</code> represents a small difference.</p>
<p>The derivative is the slope of the function’s small change near a point. In other words, it’s the limit of the rate of change of a given point.</p>
<p>A simple derivative transformation might look like this one:</p>
<p>$$\frac{d}{dx}x^n = nx^{n-1}$$</p>
<p>Two examples are:</p>
<p>$$\frac{d}{dx}x^3 = 3x^2$$</p>
<p>And:</p>
<p>$$\frac{d}{dx}x^5 = 5x^4$$</p>
<p>There are many more. But we won’t go into deep detail on this topic.</p>
<h4 id="heading-where-and-why-are-derivatives-so-important">Where and why are derivatives so important?</h4>
<p>Derivatives are one of the most important math tools out there. They serve as the foundation for understanding change across nearly all fields of STEM.</p>
<p>In physics (classical mechanics), derivatives are very important to find new information that draws on information that’s already made available.</p>
<p>For example, knowing how a body's position changes over time allows us to use derivatives to find its velocity and acceleration. This is crucial for self-driving cars, trains, rockets, and more.</p>
<p>Also, derivatives are the foundation of understanding how electricity works in depth. Without derivatives, there would’ve been no electromagnetic theory. Without electromagnetic theory, modern technology would not exist.</p>
<p>In machine learning, derivatives are so important that they served to create the algorithm that is one of the most important components of ChatGPT and others AI models. (backpropagation).</p>
<p>Backpropagation is in fact so important that its creators, John Hopfield and Geoffrey Hinton, won the 2024 Nobel Prize in Physics for it.</p>
<p>Also, autonomous vehicles like Tesla and Waymo use AI models called neural networks that depend on backpropagation to work.</p>
<p>It’s awesome that a math concept created in the 17th century is now one of the foundations of the current AI revolution.</p>
<h3 id="heading-what-about-integral-calculus">What About Integral Calculus?</h3>
<p>Before explaining derivatives further, I will ask you a question:</p>
<p>How can we find the area of the below shape?</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764401826343/2583b3b0-0bcd-4204-921e-300b27c9fc3d.png" alt="Image of a finite integral of the function sin(x)" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>In other words how can we find the integral of the function in the given interval?</p>
<p>Let’s see how to do it step by step.</p>
<p>First, we’ll try using 2 rectangles to approximate the area behind the curve:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764402058848/5023772e-ed0d-4efc-a5cd-3e1a856f6d69.png" alt="Using 2 rectangles to try to find the area under the curve" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>Now the area of the rectangles is 6.282573.</p>
<p>But there is still a lot of error…</p>
<p>As we can see, the left rectangle does not cover completely the curve and the right rectangle covers too much.</p>
<p>So we’ll add more smaller rectangles so that we can better approximate the curve.</p>
<p>Now let’s try using 4 rectangles:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764483444354/c06cd1c2-0f92-4728-898e-fbaf1534d57f.png" alt="Using 4 rectangles to try to find the area under the curve" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>Now the area is 6.497481. But there’s still some error.</p>
<p>As we can see, the error is getting smaller. In other words, the 4 rectangles cover the area of the curve better than just the 2 rectangles. But there’s still a lot of room to make it better.</p>
<p>Let’s try using 8 rectangles:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764402069389/e9ad0576-dd9d-4535-bf3a-4c4bcd77db98.png" alt="Using 8 rectangles to try to find the area under the curve" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>Now the area is 6.604935.</p>
<p>How about using 16 rectangles?</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764402075078/6ad6278f-4b71-411b-8552-2554152a04cb.png" alt="Using 16 rectangles to try to find the area under the curve" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>Now the area is 6.658662.</p>
<p>Let’s try using 32 rectangles:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764402079649/4e673391-7e7a-4ca3-b07a-22508c5b058e.png" alt="Using 32 rectangles to try to find the area under the curve" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>Now the area is 6.685525.</p>
<p>Now how about using 64 rectangles:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764402084920/4851d710-ff9d-4562-ba7d-9b759473f577.png" alt="Using 64 rectangles to try to find the area under the curve" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>Now the area is 6.698957.</p>
<p>And using 128 rectangles:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764402090280/bd5b139c-58e1-4a7a-869d-5107b7eff345.png" alt="Using 128 rectangles to try to find the area under the curve" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>Now the area is 6.705673.</p>
<p>What about using 256 rectangles:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764402098061/3ee50020-0143-42b1-aea7-8c762aa33e53.png" alt="Using 256 rectangles to try to find the area under the curve" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>Now the area is 6.709031. And the error has reached 0.0000!</p>
<p>Now let’s see an animation of this:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764402052869/e9a54332-75b5-4e46-90cc-3bc09e636ad3.gif" alt="GIF animation of the rectangles from 2 to 256 to represent the finite integral" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>As you can see, we can approximate the area by having a limit to infinity to the number of rectangles to approximate the area.</p>
<p>This way, we can conclude that:</p>
<p>$$F(x) = \int_0^{3.14} f(x) , dx = \int_0^{3.14} (\sin(x) + 1.5) , dx = 6.71$$</p>
<p>This means that the area between 0 and 3.14, limited by the math equation, is 6.71!</p>
<p>Or, mathematically, the integral of f(x) in the interval 0 and 3.14 is 6.71.</p>
<h4 id="heading-where-and-how-is-this-applied">Where and how is this applied?</h4>
<p>In electrical engineering, integrals calculate total energy use in circuits by integrating power over time. For example, when designing a power supply for a device, engineers integrate the power to determine total energy costs and heat absorption requirements.</p>
<p>In other words, they see the area over time and how much power is used.</p>
<p>Let's see an example:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764832775180/911672dd-05ff-47c7-ac5f-81f4933c96ff.png" alt="Image of integral" style="display:block;margin:0 auto" width="1500" height="900" loading="lazy">

<p>Imagine that in the image above:</p>
<ul>
<li><p>The X axis can be the time in months.</p>
</li>
<li><p>The Y axis is the power used in Watts (Joules per second).</p>
</li>
</ul>
<p>We can conclude that in 3.14 months(3 months and 4 days) the total amount of energy is 6.71 watt-months.</p>
<p>Here is the code to find that out:</p>
<pre><code class="language-plaintext"># Import libraries
import numpy as np
import matplotlib.pyplot as plt

# Create Function
x = np.linspace(0, 3.14, 100)
y = np.sin(x) + 1.5

# Find the area under the function
area = np.trapezoid(y, x)

# Show the final image
plt.fill_between(x, y)
plt.title(f'Area = {area:.2f}')
plt.show()
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765435075995/defc251b-812c-44ae-8b67-9a323c0af040.png" alt="Code to find finite integral of the function sin between two points" style="display:block;margin:0 auto" width="2080" height="1384" loading="lazy">

<p>In this code, we import the libraries, create the function, and find the area and plot it.</p>
<p>We used numpy.trapezoid to find the area, because it’s a numerical approximation to quickly find the integral of a function between two x values.</p>
<p>numpy.trapezoid uses a numerical approximation method called the <strong>composite trapezoidal rule.</strong></p>
<p>The basic idea of the composite trapezoidal rule is to divide the area under the curve into many trapezoids and sum all of them.</p>
<p>If you want to learn more about this, I recommend reading the <a href="https://numpy.org/doc/stable/reference/generated/numpy.trapezoid.html">NumPy documentation on this method</a>.</p>
<p>From this value, we can convert to other units:</p>
<ul>
<li><p>52,400,000 joules</p>
</li>
<li><p>14.6 kWh</p>
</li>
</ul>
<p>By converting to other units, we can more easily compare this device with other devices and see if it obeys any technical standards and laws.</p>
<p><strong>This is a real-life application of integrals in engineering.</strong></p>
<p>In my degree, I used this a lot in classes related to power engineering. In simple words, power engineering is a subfield of electrical engineering focused on working with electricity with very high voltage values and electric motors.</p>
<p>In audio compression, the Fourier transform (built on integrals) decomposes sound waves into frequency components. MP3 encoders use this to identify and remove frequencies humans can't hear. This reduces file sizes while preserving quality.</p>
<p>Medical imaging relies on the Radon transform, which uses integrals to reconstruct 3D images from 2D X-ray projections. When you get a CT scan, the machine takes hundreds of X-ray "slices" at different angles. During this process, integrals combine "slices" into a detailed cross-sectional image of your body.</p>
<h3 id="heading-applications-in-ai-and-control-theory-calculus-in-action">Applications in AI and Control Theory: Calculus in Action</h3>
<p>Modern AI depends on derivatives that use the backpropagation algorithm.</p>
<p>When training a neural network, the system calculates partial derivatives of the error with respect to millions of parameters. This way, find out how to adjust each weight to improve performance. Without this, large language models like ChatGPT couldn't learn from data.</p>
<p>PID controllers, which stabilize the temperature in your oven or maintain altitude in aircraft autopilot systems, combine calculus ideas:</p>
<ul>
<li><p>The proportional term responds to the current error.</p>
</li>
<li><p>The integral term accumulates past errors to eliminate steady-state drift.</p>
</li>
<li><p>The derivative term predicts future trends to prevent overshooting.</p>
</li>
</ul>
<p>And these are just some of the applications of calculus!</p>
<h2 id="heading-chapter-6-probability-amp-statistics-learning-from-uncertainty">Chapter 6: Probability &amp; Statistics - Learning from Uncertainty</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765002445093/b606e188-969e-49d8-9be9-9c15330a2939.jpeg" alt="Many purple dice together" style="display:block;margin:0 auto" width="6016" height="4000" loading="lazy">

<p><a href="https://www.pexels.com/photo/purple-dices-with-different-geometrical-shape-on-a-white-surface-3649115/">Photo by Armando Are</a></p>
<p>It’s thanks to probabilities and statistics that many industries have grown so much. With statistics, we can make informed decisions and optimize many different processes. With probabilities, we can understand and model uncertainty in systems and, in this way, solve or even avoid problems.</p>
<p>While you may be familiar with some of the key concepts like median and mean, we’ll start with some basics to build up your intuition on more advanced stuff like the central limit theorem, Bayes’ theorem, and Markov chains.</p>
<h3 id="heading-mean-median-mode-measuring-central-tendency">Mean, Median, Mode: Measuring Central Tendency</h3>
<p>Let's imagine you are a data scientist working in research. You’re going to work with data to optimize the output of farms in the Central Valley in California.</p>
<p>The idea is to take in a bunch of data, and by studying it, you can help farmers make better decisions.</p>
<p>Here’s the data from one year of activity:</p>
<table>
<thead>
<tr>
<th>Farm</th>
<th>Yield (tons/ha)</th>
<th>Fertilizer Used (kg/ha)</th>
<th>Rainfall (mm)</th>
</tr>
</thead>
<tbody><tr>
<td>A</td>
<td>4.2</td>
<td>150</td>
<td>280</td>
</tr>
<tr>
<td>B</td>
<td>5.8</td>
<td>220</td>
<td>420</td>
</tr>
<tr>
<td>C</td>
<td>3.9</td>
<td>120</td>
<td>230</td>
</tr>
<tr>
<td>D</td>
<td>6.1</td>
<td>250</td>
<td>480</td>
</tr>
<tr>
<td>E</td>
<td>4.7</td>
<td>200</td>
<td>340</td>
</tr>
<tr>
<td>F</td>
<td>5.3</td>
<td>200</td>
<td>390</td>
</tr>
</tbody></table>
<p>We have 6 farms in our dataset. For each farm, we know:</p>
<ul>
<li><p>How much yield was obtained in tons per hectare</p>
</li>
<li><p>How much fertilizer was used in kilograms per hectare</p>
</li>
<li><p>How much rainfall happened during a year of activity</p>
</li>
</ul>
<p>Now, let’s answer some questions we might have about the data to understand the <strong>mean</strong>, <strong>mode</strong> and <strong>median</strong>:</p>
<h4 id="heading-1-what-is-the-average-yield-during-one-year-of-activity">1. What is the average yield during one year of activity?</h4>
<p>To find the average, we just need to sum all the yield values and divide by the number of farms. Like this:</p>
<p>$$\text{Mean} = \frac{4.2 + 5.8 + 3.9 + 6.1 + 4.7 + 5.3}{6} = \frac{30}{6} = 5$$</p>
<p>This is what is called the mean. The mean is just the sum of all values divided by how many values there are.</p>
<p>In Python, we can do the following to calculate the mean:</p>
<pre><code class="language-plaintext">def calculate_mean(values):
    return sum(values) / len(values)

# Example usage
data = [4.2, 5.8, 3.9, 6.1, 4.7, 5.3]
result = calculate_mean(data)
print(f"Mean: {result}")
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763102054838/b5619d92-95ca-4c50-bb32-39d6e8e7ba7b.png" alt="Python code in an image showing how to find the mean" style="display:block;margin:0 auto" width="2080" height="1024" loading="lazy">

<h4 id="heading-2-what-is-the-mode-of-fertilizer-used">2. What is the mode of fertilizer used?</h4>
<p>The mode is just the most popular value in a given dataset. In our case, it’s <strong>200</strong> since that’s the most common value that appears in our farm dataset.</p>
<p>In Python, we can do this to calculate the mode:</p>
<pre><code class="language-plaintext">import statistics

def calculate_mode(values):
    return statistics.mode(values)

# Example usage
data = [150, 220, 120, 250, 200, 200]
result = calculate_mode(data)
print(f"Mode: {result}")
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763102576660/3ca71e03-f762-44ad-85c3-8ccb4cb1db54.png" alt="Python code in an image showing how to find the mode" style="display:block;margin:0 auto" width="2080" height="1204" loading="lazy">

<h4 id="heading-3-what-is-the-median-of-the-yield">3. What is the median of the yield?</h4>
<p>The median is just the value in the middle of a set of numbers. If the number of elements in the list is even, we take the mean of the two middle numbers. Here are our current yield values:</p>
<p>$$4.2, 5.8, 3.9, 6.1, 4.7, 5.3$$</p>
<p>First, we sort the values:</p>
<p>$$3.9, 4.2, 4.7, 5.3, 5.8, 6.1$$</p>
<p>Since we have 6 values (even number), the median is the average of the two middle values:</p>
<p>$$\text{Median} = \frac{4.7 + 5.3}{2} = \frac{10}{2} = 5$$</p>
<p>In Python we can do this to calculate the median:</p>
<pre><code class="language-plaintext">import statistics

def calculate_median(values):
    return statistics.median(values)

# Example usage
data = [4.2, 5.8, 3.9, 6.1, 4.7, 5.3]
result = calculate_median(data)
print(f"Median: {result}")
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763102389405/52e5009b-6bc8-42c5-b8da-efe8c372fe96.png" alt="Python code in an image showing how to find the median" style="display:block;margin:0 auto" width="2080" height="1204" loading="lazy">

<h3 id="heading-variance-and-standard-deviation-measuring-spread">Variance and Standard Deviation: Measuring Spread</h3>
<p>Knowing the mean, mode, and median of data is helpful. But it’s also important to know how far away data points are from each other.</p>
<p>That’s where measures of <a href="https://en.wikipedia.org/wiki/Statistical_dispersion">dispersion</a> come in. Variance tells us, on average, how far numbers are from the mean.</p>
<p>Let’s see an example of how to calculate this.</p>
<p>Given yield data from the table:</p>
<p>$$4.2, 5.8, 3.9, 6.1, 4.7, 5.3$$</p>
<p>The first step is the calculate the mean:</p>
<p>$$\bar{x} = \frac{4.2 + 5.8 + 3.9 + 6.1 + 4.7 + 5.3}{6} = \frac{30}{6} = 5$$</p>
<p>The second step is to calculate the variance with the sample variance formula:</p>
<p>$$s^2 = \frac{\sum_{i=1}^{n}(x_i - \bar{x})^2}{n-1}$$</p>
<p>Let's apply the formula little by little to understand how it works.</p>
<p>We will first we will calculate the variance of each yield data point:</p>
<p>$$\begin{align*} (4.2 - 5.0)^2 &amp;= (-0.8)^2 = 0.64 \ (5.8 - 5.0)^2 &amp;= (0.8)^2 = 0.64 \ (3.9 - 5.0)^2 &amp;= (-1.1)^2 = 1.21 \ (6.1 - 5.0)^2 &amp;= (1.1)^2 = 1.21 \ (4.7 - 5.0)^2 &amp;= (-0.3)^2 = 0.09 \ (5.3 - 5.0)^2 &amp;= (0.3)^2 = 0.09 \end{align*}$$</p>
<p>Then we will sum all the squared differences:</p>
<p>$$\sum(x_i - \bar{x})^2 = 0.64 + 0.64 + 1.21 + 1.21 + 0.09 + 0.09 = 3.88$$</p>
<p>Now, we will finally find the variance:</p>
<p>$$s^2 = \frac{3.88}{6-1} = \frac{3.88}{5} = 0.776$$</p>
<p>The standard deviation is just the square root of the variance.</p>
<p>$$s = \sqrt{s^2} = \sqrt{0.776} \approx 0.881 tons/ha$$</p>
<p>Why is this useful?</p>
<p>It puts the spread back into the same units as the data, making it easier to interpret.</p>
<p>A small standard deviation means the data huddles close to the mean, while a large one means it’s widely scattered.</p>
<p>And here is a code example of how to calculate both:</p>
<pre><code class="language-plaintext">import statistics

def calculate_variance_and_std(values):
    variance = statistics.variance(values)
    std_dev = statistics.stdev(values)
    return variance, std_dev

# Example usage
data = [4.2, 5.8, 3.9, 6.1, 4.7, 5.3]
variance, std_dev = calculate_variance_and_std(data)
print(f"Variance: {variance}")
print(f"Standard Deviation: {std_dev}")
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763102806607/a8236667-e4b0-48a5-9171-544c4b94096e.png" alt="Python code in an image showing how to find the variance and standard deviation" style="display:block;margin:0 auto" width="2148" height="1472" loading="lazy">

<h3 id="heading-what-is-the-normal-distribution-the-bell-curve-of-life">What Is the Normal Distribution? The Bell Curve of Life</h3>
<p>The normal distribution tells us how data naturally converges around the average value. Most values are focused on the center, and extreme values are more to the edges. This creates a bell curve.</p>
<p>By understanding this distribution, we can understand other distributions and also the central limit theorem.</p>
<p>To understand what normal distribution is, let’s look at it:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763529094535/f90ffdb8-543e-4d1f-9627-335e8f356512.png" alt="Image representing the normal distribution" style="display:block;margin:0 auto" width="582" height="426" loading="lazy">

<p>The normal distribution looks like like a mountain.</p>
<p>As you can see, most values are around the mean. Also, in and around the mean is the peak. Toward the extremes, the curve gets lower and lower. This means that in the extremes there are fewer and fewer values.</p>
<p>Normal distribution also has a formula associated with it:</p>
<p>$$f(x) = \frac{1}{\sqrt{2\pi\sigma^2}} \exp\left( -\frac{(x-\mu)^2}{2\sigma^2} \right)$$</p>
<p>I won’t go in depth into how the formula works here. I just want you to understand the main idea behind the concept.</p>
<p>There are many other distributions besides the normal distribution. Some of the most common are:</p>
<ul>
<li><p>Chi-squared distribution</p>
</li>
<li><p>Student’s t distribution</p>
</li>
<li><p>Bernoulli distribution</p>
</li>
<li><p>Binomial distribution</p>
</li>
<li><p>Poisson distribution</p>
</li>
</ul>
<p>Each distribution can model different events and phenomenons. For example the Chi-squared distribution is widely used to find the correlation between two phenomenons (sunburns and skin cancer, for example).</p>
<p>The Poisson distribution is also used in modeling counts of events, like the number of clients that enter a store per hour or the number of data packets that are transmitted in a Ethernet cable.</p>
<p>But it’s also possible to approximate a lot of distributions to the normal distribution using one of the most important theorems in all of mathematics: the central limit theorem. This is what we will explore next.</p>
<h3 id="heading-how-the-central-limit-theorem-helps-approximate-the-world">How the Central Limit Theorem Helps Approximate the World</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766902263857/9a03bb38-a7b9-4ef0-93f2-a7e0d80bd249.jpeg" alt="Person holding a small version of the world in their hand" style="display:block;margin:0 auto" width="5184" height="3456" loading="lazy">

<p>Photo by <a href="https://www.pexels.com/photo/person-holding-world-globe-facing-mountain-346885/">Porapak Apichodilok</a></p>
<p>The main idea of the central limit theorem is very simple:</p>
<ul>
<li>Most distributions can be approximated to become the normal distribution.</li>
</ul>
<p>This is just like pouring sand into a funnel. Grains may fall randomly, but over time the pile of sand will&nbsp;always begin to form the shape of a mountain.</p>
<p>This way, we can take many data points and average them. Over time, it will converge to become a normal distribution.</p>
<p>In other words, when independent random variables are all summed together, their sum tends toward a normal distribution.</p>
<p>Here is the formula:</p>
<p>$$\bar{X} \approx N\left(\mu, \frac{\sigma^2}{n}\right) \quad \text{or equivalently} \quad Z = \frac{\bar{X} - \mu}{\sigma/\sqrt{n}} \approx N(0, 1)$$</p>
<p>You don’t need to understand in depth what it means. Just understand that it’s a theorem that approximates other distributions to the normal distribution.</p>
<h4 id="heading-and-why-is-this-important">And why is this important?</h4>
<p>Because this theorem makes many billion-dollar industries possible.</p>
<p>Instead of testing every single possible scenario, we can test for a smaller amount of scenarios and assume that if it works for the smaller one, it will work for the bigger one.</p>
<p>For example, in telecommunications, instead of testing every possible phone call or data transmission, we can just test a few connections. If it works for those few connections, we can assume it will work for millions of phone and data transmissions.</p>
<p>For clinical trials, instead of testing a drug on millions of people, we can just test a smaller number of patients. If it works for a (relative) few patients, we can assume it will work on most people with the same condition.</p>
<p>Without this idea, clinical trials would not be possible. The same with telecommunications and so many other areas of engineering.</p>
<h3 id="heading-bayes-theorem-learning-from-evidence">Bayes Theorem: Learning from Evidence</h3>
<p>Now we’ll start looking at probability more in depth based on the data table we have been using.</p>
<p>Here’s the table again so that you can reference it more easily:</p>
<table>
<thead>
<tr>
<th>Farm</th>
<th>Yield (tons/ha)</th>
<th>Fertilizer Used (Kg/ha)</th>
<th>Rainfall (mm)</th>
</tr>
</thead>
<tbody><tr>
<td>A</td>
<td>4.2</td>
<td>150</td>
<td>280</td>
</tr>
<tr>
<td>B</td>
<td>5.8</td>
<td>220</td>
<td>420</td>
</tr>
<tr>
<td>C</td>
<td>3.9</td>
<td>120</td>
<td>230</td>
</tr>
<tr>
<td>D</td>
<td>6.1</td>
<td>250</td>
<td>480</td>
</tr>
<tr>
<td>E</td>
<td>4.7</td>
<td>200</td>
<td>340</td>
</tr>
<tr>
<td>F</td>
<td>5.3</td>
<td>200</td>
<td>390</td>
</tr>
</tbody></table>
<p>Now there are a lot of ideas and formulas related to probabilities. But here, I want to explain to you the core ones that are applied in AI and give you a high-level definition of things.</p>
<p>We’ll start with conditional probability, which is foundational to understanding Bayes’ theorem. Then we’ll get to the extended Bayes’ theorem formula.</p>
<p>So, let's get started!</p>
<h4 id="heading-what-is-conditional-probability">What is Conditional Probability?</h4>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766903189931/420cc60a-71cd-4c37-ab0a-f8aebe825ca7.jpeg" alt="Image of a person playing chess with the black pieces" style="display:block;margin:0 auto" width="6000" height="4000" loading="lazy">

<p>Photo by <a href="https://www.pexels.com/photo/black-and-yellow-chess-pieces-3830671/">KOUSHIK BALA</a></p>
<p>Conditional probability is the probability that an event will happen given that another event has already taken place.</p>
<p>Confused? Don't worry! Let's see an example:</p>
<p>Let’s say that:</p>
<ul>
<li><p>A = Farm has rainfall above or equal 400 mm</p>
</li>
<li><p>B = Farm has a yield above or equal to 5.0 tons/ha</p>
</li>
</ul>
<p>Here is the formula for Conditional Probability:</p>
<p>$$P(A|B) = \frac{P(A \cap B)}{P(B)}$$</p>
<p>Now let’s see this formula more in detail:</p>
<p>$$P(A)$$</p>
<p>This represents the probability that a farm has rainfall above or equal to 400 mm.</p>
<p>We have 6 farms, and 2 of them (farm B and D) have a rainfall above or equal to 400 mm.</p>
<p>So, the probability that a farm has rainfall above or equal to 400 mm is:</p>
<p>$$P(A) = \frac {2}{6} = \frac {1}{3} ≈ 0.33$$</p>
<p>Now let’s see for event B:</p>
<p>$$P(B)$$</p>
<p>This represents the probability that a farm has a yield above or equal to 5.0 tons/ha.</p>
<p>We have 6 farms and 3 of them (farm B, D and F) have a yield above or equal to 5.0 tons/ha.</p>
<p>So, the probability that a farm has a yield above or equal to 5.0 tons/ha is:</p>
<p>$$P(B) = \frac {3}{6} = \frac {1}{2} = 0.5$$</p>
<p>What about if we want to see both conditions’ probabilities at the same time?</p>
<p>$$P(A \cap B)$$</p>
<p>This refers to the probability of A and B being both true.</p>
<p>In our example, in means the probability that a farm both has a rainfall above or equal to 400 mm <strong>and</strong> a yield above or equal to 5.0 tons/ha.</p>
<p>We have:</p>
<ul>
<li><p>6 farms and 2 of them (farm B and D) have a rainfall above or equal 400 mm</p>
</li>
<li><p>6 farms and 3 of them (farm B, D and F) have a yield above or equal to 5.0 tons/ha</p>
</li>
</ul>
<p>For A and B to be true, only 2 farms (farm B and D) have both conditions.</p>
<p>This way:</p>
<p>$$P(A \cap B) = \frac {2}{6} = \frac {1}{3} ≈ 0.33$$</p>
<p>Now we’re ready to find out the conditional probability:</p>
<p>$$P(A|B)$$</p>
<p>This means the probability of A, knowing that B is true.</p>
<p>In our example, we can conclude that:</p>
<p>$$P(A|B) = \frac{P(A \cap B)}{P(B)} = \frac{0.33}{0.5} = 0.66$$</p>
<p>So, the probability that a farm has rainfall above or equal 400 mm – knowing that it has a yield above or equal to 5.0 tons/ha – is 0.66</p>
<h4 id="heading-bayes-theorem">Bayes’ Theorem</h4>
<p>This is one of the most important theorems in mathematics.</p>
<p>Bayes’ theorem is a formula that tells us how to change the probability of a prediction when new verified data becomes available.</p>
<p>In other words, it’s like a rule that tells us how to update our beliefs when new evidence appears.</p>
<p>Now, based on what we already know, let’s see how Bayes’ Theorem works.</p>
<p>Here is its formula:</p>
<p>$$P(B|A) = \frac{P(A|B) \cdot P(A)}{P(B)}$$</p>
<p>Now, based on the previous values, we can very easily find the probability of B, given that A is true.</p>
<p>In other words, the probability that a farm has a yield above or equal to 5.0 tons/ha given that is has a rainfall above or equal to 400 mm.</p>
<p>Let’s find the answer:</p>
<p>$$P(B|A) = \frac{P(A|B) \cdot P(A)}{P(B)}= \frac{0.66 \cdot 0.33}{0.5}=0.44$$</p>
<p>So, the probability that a farm has a a yield above or equal to to 5.0 tons/ha, knowing it rained equal to or more than 400 mm, is 44%.</p>
<p>Now that we’ve gone through this formula step by step, hopefully it doesn’t feel as complex.</p>
<h4 id="heading-where-is-this-applied-in-real-life">Where is this applied in real life?</h4>
<p>As with many math ideas in this book, Bayes' Theorem has applications in many business sectors.</p>
<p>For example, what is the best way to make a control system for a self-driving car, robot, or really any other device?</p>
<p>One effective approach is to use a <a href="https://en.wikipedia.org/wiki/Kalman_filter">Kalman filter</a>. Kalman filters rely heavily on Bayes' Theorem to handle control systems with incomplete data.</p>
<p>Kalman filters have a lot of applications in engineering. For example, thanks to Kalman filters, commercial jets can fly safely on autopilot.</p>
<p>So as you can see, Bayes’ Theorem is the foundation of many control systems used in risky industries.</p>
<h3 id="heading-what-are-markov-models-predicting-the-next-step-one-step-at-a-time">What Are Markov Models? Predicting the Next Step, One Step at a Time</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766902389612/c80d7118-f13d-4f9b-a149-861db3f2037d.jpeg" alt="Image of the hand of a person throwing dice into the air" style="display:block;margin:0 auto" width="6000" height="4000" loading="lazy">

<p>Photo by <a href="https://www.pexels.com/photo/person-about-to-catch-four-dices-1111597/">lil artsy</a></p>
<p>How do you predict the future with math? Markov chains allow you to do this to a certain degree.</p>
<p>For this reason, Markov chains are widely used in science, engineering, economics, and many other areas.</p>
<p>In addition to this, Markov decision processes are a very important foundation for reinforcement learning. Reinforcement learning is a branch of AI where agents learn to make decisions by interacting with an environment to maximize rewards.</p>
<p>In this section, I’ll introduce you to Markov chains and decision processes with an analogy, a plain English explanation, and a code example.</p>
<p>If you want to dive in further, I recommend my <a href="https://www.freecodecamp.org/news/what-is-a-markov-chain/">freeCodeCamp article on the subject</a>.</p>
<h4 id="heading-markov-chain-analogy">Markov Chain Analogy</h4>
<p>Imagine that you want to predict the weather tomorrow, and it <strong>only</strong> depends on the weather today. The weather can be either sunny or rainy.</p>
<p>Here are the probabilities:</p>
<ul>
<li><p>If it's sunny today, there's an 80% chance that it will be sunny again tomorrow, and a 20% chance that it will be rainy.</p>
</li>
<li><p>If it's rainy today, there's a 50% chance that it will be sunny tomorrow, and a 50% chance that it will be rainy.</p>
</li>
</ul>
<p>In this scenario, we can predict future states of the weather based on current states using probabilities.</p>
<p>This idea of predicting the future based solely on probabilities of the present is called a Markov chain.</p>
<p>Here, the states are either sunny or rainy and the probabilities describe the chances of the weather changing based on the current state.</p>
<h4 id="heading-markov-chain-explained-in-plain-english">Markov Chain Explained in Plain English</h4>
<p>A Markov chain describes random processes where systems move between states, and a new state only depends on the current state, not on how it got there.</p>
<p>Mathematically, Markov chains are called stochastic models because they model (simulate) real life events that are random by nature (stochastic).</p>
<p>Markov chains are popular because they are easy to implement and efficient at modeling complex systems.</p>
<p>Another key advantage is their "memoryless" property. This makes it faster to run on computers, and powerful to study random processes and make predictions based on current conditions.</p>
<h4 id="heading-applications-of-markov-chains">Applications of Markov Chains</h4>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766902558494/8129d378-5cd8-4fdc-be48-8ba0a34181b7.jpeg" alt="Image of a white square with a dark star inside it, surrounded by many other dark squares" style="display:block;margin:0 auto" width="3840" height="2160" loading="lazy">

<p>Photo by <a href="https://www.pexels.com/photo/shapes-on-a-dark-background-25630338/">Google DeepMind</a></p>
<p>At some level, almost all real-life events are stochastic. In other words, they involve randomness and uncertainty.</p>
<p>This is exactly why they are so widely used.</p>
<p>They can predict the behavior of systems based on current conditions:</p>
<ul>
<li><p>In finance, they are used to detect changes in credit ratings for forecasting market regimes.</p>
</li>
<li><p>In genetics, they help understand how proteins change over time (which is important when studying genetic variations).</p>
</li>
</ul>
<p>These real life examples show how effective Markov chains can be used to solve real problems in different fields.</p>
<p>In AI, Markov chains are used to model an environment like a factory or home. Modeling an environment with Markov chains is called a Markov decision process.</p>
<p>Using a Markov decision process, it’s possible to use reinforcement learning to create and optimize agents to act in the environment.</p>
<p>Of course, new and better variants of the Markov decision process have appeared over the years. But the key idea here is that it is thanks to Markov decision processes that the basis for reinforcement learning exists.</p>
<p>Reinforcement learning is widely used in advertising systems, logistics, robotics, video games, and many more applications.</p>
<h4 id="heading-types-of-markov-chains">Types of Markov Chains</h4>
<p>There are many types of Markov chains. In this section, we'll only discuss the most important variants.</p>
<ol>
<li>Discrete-Time Markov Chains (DTMCs)</li>
</ol>
<p>In DTMCs, the system changes state at specific time steps. They are called discrete because the state transitions occur at distinct, separate time intervals.</p>
<p>They are used in queuing theory (study of the behavior of waiting lines), genetics, and economics because they are simple to analyze.</p>
<ol>
<li>Continuous-Time Markov Chains (CTMCs)</li>
</ol>
<p>CTMCs differ from DTMCs in that state transitions can occur at any continuous time point, not at fixed intervals.</p>
<p>This makes them stochastic models where state changes happen continuously. This is important in chemical reactions and reliability engineering.</p>
<ol>
<li>Reversible Markov Chains</li>
</ol>
<p>Reversible Markov chains are special. The process of state change is the same whether the direction is forwards or backwards, like rewinding a video and playing it again.</p>
<p>This property makes it easier to know when a system is stable and study how a system behaves over time. They are widely used in statistical physics and economics</p>
<ol>
<li>Doubly Stochastic Markov Chains</li>
</ol>
<p>Doubly stochastic Markov chains are defined by a transition probability matrix. In the matrix, the sum of the probabilities in each row and each column equals 1.</p>
<p>This means each row and each column represent a valid probability distribution. In other words, each row and column represent a list of chances for different outcomes.</p>
<p>This property is crucial in quantum computing and statistical mechanics.</p>
<p>Thanks to Doubly stochastic Markov chains, systems change in a way that preserves probabilities and symmetry, making the modeling and analysis of quantum computing systems far more accurate.</p>
<h4 id="heading-hidden-markov-chains-code-example">Hidden Markov Chains Code Example</h4>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766903059652/ad8c6509-87ae-4978-8b64-24146161d1cb.jpeg" alt="Image of glasses, a MAC computer, and blurry code in it" style="display:block;margin:0 auto" width="3353" height="2514" loading="lazy">

<p>Photo by <a href="https://www.pexels.com/photo/data-codes-through-eyeglasses-577585/">Kevin Ku</a></p>
<p>Before we jump into code examples, let’s first understand what Hidden Markov Chains are.</p>
<p>The main idea behind hidden Markov chains is to model systems that have hidden states (states for which we don’t know their values) which can only be discovered through observable events.</p>
<p>In other words, hidden Markov chains allow us to predict the behavior of a system by:</p>
<ul>
<li><p>Considering the likelihood of moving from one state to another.</p>
</li>
<li><p>Knowing the probability of observing a certain event from each state</p>
</li>
</ul>
<p>We can understand this by observing how the states change from an indirect point of view.</p>
<p>We may not know the states’ original values. But by knowing the way they change, we can predict what their values will be in the future.</p>
<p>This way, hidden Markov chains are flexible in modeling sequences, capturing both the transitions between hidden states and the observable outcomes.</p>
<p>Because of this, hidden Markov models are used in fields such as engineering, financial modeling, speech recognition, bioinformatics, and many more.</p>
<h4 id="heading-code-example">Code Example:</h4>
<p>In this code example, we’ll see a simple example with synthetic data.</p>
<p>Here is the full code:</p>
<pre><code class="language-python">import numpy as np
from hmmlearn import hmm

# Set random seed for reproducibility
np.random.seed(42)

# Define the HMM parameters
n_components = 2  # Number of states
n_features = 1    # Number of observation features

# Create a Gaussian HMM
model = hmm.GaussianHMM(n_components=n_components, covariance_type="diag")

# Define transition matrix (rows must sum to 1)
model.startprob_ = np.array([0.6, 0.4])
model.transmat_ = np.array([[0.7, 0.3],
                            [0.4, 0.6]])

# Define means and covariances for each state
model.means_ = np.array([[0.0], [3.0]])
model.covars_ = np.array([[0.5], [0.5]])

# Generate synthetic observation data
X, Z = model.sample(100)  # 100 samples

# Create a new HMM instance
new_model = hmm.GaussianHMM(n_components=n_components, covariance_type="diag", n_iter=100)

# Fit the model to the data
new_model.fit(X)

# Print the learned parameters
print("Transition matrix:")
print(new_model.transmat_)
print("Means:")
print(new_model.means_)
print("Covariances:")
print(new_model.covars_)

# Predict the hidden states for the observed data
hidden_states = new_model.predict(X)

print("Hidden states:")
print(hidden_states)
</code></pre>
<img src="https://cdn-media-0.freecodecamp.org/2024/06/1.png" alt="Full code example of HMM (Hidden Markov Chain)" style="display:block;margin:0 auto" width="2000" height="2528" loading="lazy">

<p>Now let’s break the code down block by block:</p>
<p><strong>Import libraries and set random seed:</strong></p>
<pre><code class="language-python">import numpy as np
from hmmlearn import hmm

np.random.seed(42)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763529887680/2440547e-ccf4-4067-83c2-20fafb16f045.png" alt="Code example of HMM (Hidden Markov Chain) - Import libraries and set random seed" style="display:block;margin:0 auto" width="2080" height="772" loading="lazy">

<p>In this block of code, we imported two Python libraries:</p>
<ul>
<li><p><a href="https://numpy.org/">NumPy</a>: For numerical operations.</p>
</li>
<li><p><a href="https://hmmlearn.readthedocs.io/en/latest/index.html">hmmlearn</a>: For hidden Markov model implementation.</p>
</li>
</ul>
<p>Next we defined a random seed with the NumPy library. A random seed is a value used to start a pseudorandom number generator.</p>
<p>With a fixed random seed, we can ensure that the sequence of pseudorandom numbers generated is always the same. This allows us to duplicate experiments and verify results.</p>
<p>The specific value of the seed doesn’t matter as long as it remains consistent.</p>
<p><strong>Define the HMM parameters and create a Gaussian HMM:</strong></p>
<pre><code class="language-python">n_components = 2  # Number of states
n_features = 1    # Number of observation features

model = hmm.GaussianHMM(n_components=n_components, covariance_type="diag")
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763529894398/094ac272-2788-4856-a984-b1f687464e90.png" alt="Code example of HMM (Hidden Markov Chain) - Define the HMM parameters and create a Gaussian HMM" style="display:block;margin:0 auto" width="2988" height="772" loading="lazy">

<p>In this code block, we created an HMM with two hidden states and a single observed variable.</p>
<p><code>covariance_type "diag"</code> means the matrices that represent covariance (how two variables change together) are diagonal. In other words, each row and column is assumed to be independent of the others.</p>
<p>This implies that the probability distributions of each row and column are independent of each other.</p>
<p>But there is still something strange when we defined the hidden Markov chain:</p>
<p><strong>What does “Gaussian“ mean?</strong></p>
<p>This is a very big topic in statistics, but in a few words, Markov chains can only be created when we specify the transition probabilities (chances of moving from one state to another in a Markov chain) and an initial probability distribution.</p>
<p>A Gaussian HMM assumes events are initially modeled by a Gaussian distribution, also called a normal distribution!</p>
<p>And recall, we have already seen before what a normal distribution is.</p>
<p>Here is it again:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763529107399/e51cb7a3-e751-45c7-8164-c07795ad32e1.png" alt="Code example of HMM (Hidden Markov Chain) - Image of normal distribution" style="display:block;margin:0 auto" width="582" height="426" loading="lazy">

<p>From a normal distribution and other components, we can create a hidden Markov chain. And hidden Markov chains serve as a foundation for systems that affect millions of lives.</p>
<p><strong>Define transition matrix, means, and covariances for each state:</strong></p>
<pre><code class="language-python">model.startprob_ = np.array([0.6, 0.4])
model.transmat_ = np.array([[0.7, 0.3],
                            [0.4, 0.6]])

model.means_ = np.array([[0.0], [3.0]])
model.covars_ = np.array([[0.5], [0.5]])
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763529901607/53442504-bcec-46d0-8114-fcd627947576.png" alt="Code example of HMM (Hidden Markov Chain) - Define transition matrix, means, and covariances for each state" style="display:block;margin:0 auto" width="2080" height="952" loading="lazy">

<pre><code class="language-python">model.startprob_ = np.array([0.6, 0.4])
</code></pre>
<p>This line sets the initial state probabilities for a Hidden Markov Model (HMM). It points out that there is a 60% probability of starting in state 0 and a 40% probability of starting in state 1.</p>
<pre><code class="language-python">model.transmat_ = np.array([[0.7, 0.3], [0.4, 0.6]])
</code></pre>
<p>This line of code sets the state transition probability matrix for the HMM.</p>
<p>The matrix specifies the probabilities of moving from one state to another:</p>
<ul>
<li><p>From state 0, there is a 70% chance of staying in state 0 and a 30% chance of transitioning to state 1.</p>
</li>
<li><p>From state 1, there is a 40% chance of transitioning to state 0 and a 60% chance of staying in state 1.</p>
</li>
</ul>
<pre><code class="language-python">model.means_ = np.array([[0.0], [3.0]])
</code></pre>
<p>This line sets the mean values for the observation distributions in each state.</p>
<p>It indicates that the observations are normally distributed with a mean of 0.0 in state 0 and a mean of 3.0 in state 1.</p>
<pre><code class="language-python">model.covars_ = np.array([[0.5], [0.5]])
</code></pre>
<p>This line sets the covariance values for the observation distributions in each state.</p>
<p>It specifies that the variance (covariance in this 1-dimensional case) of the observations is 0.5 for both state 0 and state 1.</p>
<p><strong>Create data, new HMM instance, and fit the model with the data:</strong></p>
<pre><code class="language-python">X, Z = model.sample(100)  # 100 samples

new_model = hmm.GaussianHMM(n_components=n_components, covariance_type="diag", n_iter=100)

new_model.fit(X)

print("Transition matrix:")
print(new_model.transmat_)
print("Means:")
print(new_model.means_)
print("Covariances:")
print(new_model.covars_)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763529906427/009804bc-40db-4979-99dd-564935b175cc.png" alt="Code example of HMM (Hidden Markov Chain) - Create data, new HMM instance, and fit the model with the data" style="display:block;margin:0 auto" width="2000" height="845" loading="lazy">

<p>In this code, we created a model with 100 samples, iterated it 100 times, and printed the new state transition matrix, means, and covariances.</p>
<p>In other words, we:</p>
<ol>
<li><p>Generated 100 samples from the original model</p>
</li>
<li><p>Fitted a new HMM to these samples.</p>
</li>
<li><p>Printed the learned parameters of this new model.</p>
</li>
</ol>
<p>What do X and Z mean here?</p>
<p>X means the observed data samples generated by the original model, while Z means the hidden state sequences corresponding to the observed data samples generated by the original model.</p>
<p>The transition matrix prints out:</p>
<pre><code class="language-python">[[0.8100804  0.1899196 ]
 [0.49398918 0.50601082]]
</code></pre>
<p>Which means that the model tends to stay in state 0 and has nearly equal chances of switching or staying when in state 1.</p>
<p>The means print out:</p>
<pre><code class="language-python">[[0.01577373]
 [3.06245496]]
</code></pre>
<p>Which means that the average observed value is approximately 0.016 in state 0 and 3.062 in state 1.</p>
<p>The covariances print out:</p>
<pre><code class="language-python">[[[0.41987084]]
 [[0.53146802]]]
</code></pre>
<p>Which means that the observed values vary by about 0.420 in state 0 and 0.531 in state 1.</p>
<p>This way, we may never know the exact values of the states, but we know their average observed value and how they vary and tend to change with each other.</p>
<p><strong>Predict the hidden states for the observed data:</strong></p>
<pre><code class="language-python">hidden_states = new_model.predict(X)

print("Hidden states:")
print(hidden_states)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1763529913530/f81b3dbf-f517-4857-ac92-4732a524a621.png" alt="Code example of HMM (Hidden Markov Chain) - Predict the hidden states for the observed data" style="display:block;margin:0 auto" width="2080" height="772" loading="lazy">

<p>In this code, based on the X observed data samples, we predicted the new states of the Markov model.</p>
<p>The hidden states print out:</p>
<pre><code class="language-python">[0 0 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0 1 1 0 0 1 1 0 1 1 0 1 0 0 0 1
 1 1 1 1 0 0 0 1 1 0 0 1 1 1 1 0 0 0 0 0 0 0 1 1 0 0 0 0 0 0 0 0 1 0 0 0 0
 0 0 0 0 0 0 0 0 1 1 0 0 1 0 0 0 0 0 0 0 0 1 1 0 0 0]
</code></pre>
<p>Which means that the hidden states switch between state 0 and state 1, showing how the system changes states over time.</p>
<h3 id="heading-applications-in-ai-and-control-theory-making-decisions-under-uncertainty"><strong>Applications in AI and Control Theory: Making Decisions Under Uncertainty</strong></h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765002495967/325e5ee4-df14-4adc-a520-0764d89fe8c8.jpeg" alt="Image of many flight instruments in an airplane" style="display:block;margin:0 auto" width="5074" height="3325" loading="lazy">

<p><a href="https://www.pexels.com/photo/gray-airplane-control-panel-3402846/">Photo by capt.sopon</a></p>
<p>I have been giving you a high-level overview of the field of probabilities and statistics. As I explained before, I wanted to make the explanations simple to understand.</p>
<p>As someone with a bachelor's degree in electrical and computer engineering, I can assure you that while this chapter seems simple, in probabilities and statistics, things can get very complicated very quickly.</p>
<p>Many more concepts like:</p>
<ul>
<li><p>p-values</p>
</li>
<li><p>Advanced Monte Carlo methods</p>
</li>
<li><p>Bayesian networks</p>
</li>
<li><p>Statistical hypotheses</p>
</li>
</ul>
<p>Are not as straightforward as the ideas I’ve just told you about.</p>
<p>But as it is, probability and statistics are the starting points for making decisions where uncertainty exists in AI and control theory.</p>
<p>For example, the Bayes’ theorem, besides being the foundation of the Kalman filter, is also the foundation of many probabilistic models in the field of AI. Probabilistic models are usually used in quant firms and banks to model risk.</p>
<p>In control theory, probabilities and statistics are widely used to design robust control systems (as is the case with Kalman filters).</p>
<p>So as you can see, the application of probabilities and statistics, as with calculus and linear algebra, is the foundation for many tools that impact millions of lives and move billions of dollars in the global economy.</p>
<h2 id="heading-chapter-7-optimization-theory-teaching-machines-to-improve">Chapter 7: Optimization Theory - Teaching Machines to Improve</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765002637327/9dea740c-4582-42bf-95a6-1230b7e9092d.jpeg" alt="Black and white image of many railways originating from a single one" style="display:block;margin:0 auto" width="2560" height="1920" loading="lazy">

<p><a href="https://www.pexels.com/photo/railroad-tracks-in-city-258510/">Photo by Pixabay</a></p>
<p>This is the most advanced math chapter of the book. To truly understand it, it’s very important that you’ve first read the other chapters first.</p>
<p>We’re going to examine a few machine learning methods, and I’ll show you some recipes of how machine learning is just the use of linear algebra, calculus, probabilities and statistics, and optimization theory.</p>
<p>Just like making a cake!</p>
<h3 id="heading-what-is-optimization-theory">What is Optimization Theory?</h3>
<p>In AI, optimization theory is responsible for the algorithms that optimize data-driven AI models.</p>
<p>Often, big companies invest millions in research to create or refine algorithms that make training AI models faster.</p>
<p>This way, companies save far more money than the upfront research costs when scaling to train multiple large AI models.</p>
<p>It is thanks to optimization theory that deep learning was able to scale efficiently, eventually leading to the creation of ChatGPT and many other large language models.</p>
<p><strong>But why is that?</strong></p>
<p>In all data-driven machine learning models, there is a learning phase that has to happen. That is, there’s a period where the algorithms make predictions that are not correct and then need to change some parameters to make sure the next predictions are correct – or at least closer to being correct.</p>
<p>Without optimization, machine learning algorithms don't get anywhere on their learning path to the right solution. Without optimization, they spend too much time on a learning path that won’t increase their ability to predict things the right way.</p>
<p>So, let’s start learning!</p>
<h3 id="heading-why-optimization-drives-learning-in-ai">Why Optimization Drives Learning in AI</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766903297889/4075d065-9b55-42e2-a6f6-8aae02de940f.jpeg" alt="Image of a very cute white robot" style="display:block;margin:0 auto" width="4896" height="3264" loading="lazy">

<p><a href="https://www.pexels.com/photo/high-angle-photo-of-robot-2599244/">Photo by Alex Knight</a></p>
<p>Optimization theory is the mathematical foundation that allows algorithms to improve their performance over many iterations.</p>
<p>When we combine an algorithm with a path to change its parameters to meet a certain objective (done with an optimization method), it’s called a machine learning algorithm.</p>
<p>This learning process always involves minimizing or maximizing a certain objective. For example, for many machine learning algorithms, the main objective is to minimize errors. To do this, over many iterations, the optimization methods "tells" the internal components of an algorithm what to change after receiving feedback on how well it’s performing.</p>
<p>It’s like someone first learning how to drive a car. The first few times, it may be complicated. But after a while and some practice, the driver learns how to drive properly and not make the same mistakes they once did in the past with the help of the instructor.</p>
<p>The same applies to optimization methods when optimizing algorithms.</p>
<h4 id="heading-types-of-optimization-theory-methods-in-ml-and-deep-learning">Types of Optimization Theory Methods in ML and Deep Learning</h4>
<p>The field of optimization theory is huge! Just as with many fields of mathematics, it is constantly growing every year.</p>
<p>But for the purposes of this book, there are three main categories of optimization methods:</p>
<ol>
<li><strong>First-Order Methods</strong></li>
</ol>
<p>These are the most used in deep learning and in all LLM models like Gemini, Grok, and others.</p>
<p>They are called first-order methods because they all use the first derivative of functions. The first derivative of a function measures how much a function's output changes when its input changes very little. The most widely used in deep learning are advanced variants of gradient descent.</p>
<p>While there are many variants, here are some popular examples:</p>
<ul>
<li><p>Standard batch gradient descent</p>
</li>
<li><p>Stochastic gradient descent</p>
</li>
<li><p>Mini-batch gradient descent</p>
</li>
<li><p>RMSprop</p>
</li>
<li><p><strong>Adam</strong></p>
</li>
</ul>
<p>In this chapter, we will look in depth at one of these methods called <strong>Adam</strong> (below).</p>
<ol>
<li><strong>Second-Order Methods</strong></li>
</ol>
<p>They are called second-order methods because they use information from second derivatives for better updates. There are many methods, like:</p>
<ul>
<li><p>BFGS</p>
</li>
<li><p>L-BFGS</p>
</li>
<li><p>Newton's method</p>
</li>
</ul>
<p>But these are not often used in machine and deep learning. While they optimize with fewer iterations, for the type of optimization problems algorithms in AI create (high-dimensional problems), they’re very computationally expensive.</p>
<p>So they’re not widely used like first-order optimization methods.</p>
<ol>
<li><strong>Zeroth-Order and Other Methods</strong></li>
</ol>
<p>These methods do not require derivatives to optimize algorithms. Some examples of algorithms where derivatives are not used are:</p>
<ul>
<li><p>Genetic algorithms</p>
</li>
<li><p>Dynamic programming algorithms</p>
</li>
<li><p>Particle swarm optimization methods</p>
</li>
</ul>
<p>The problem with these algorithms is that they are often very slow for many variables.</p>
<p>But in certain AI contexts, they can help optimize the architecture of deep learning models to improve AI models from an architectural point of view (instead of a parameter point of view).</p>
<h4 id="heading-how-does-optimization-theory-connect-with-linear-algebra-calculus-and-probability-and-statistics">How does optimization theory connect with linear algebra, calculus, and probability and statistics?</h4>
<p>Essentially:</p>
<ul>
<li><p>Calculus teaches you derivatives, which help you understand optimization theory.</p>
</li>
<li><p>Linear algebra teaches you matrices, which help you understand how different states relate and transform.</p>
</li>
<li><p>Probability and statistics teach you concepts like covariance and correlation, which help you understand how variables are connected with each other.</p>
</li>
</ul>
<p>This way, with linear algebra and probability and statistics, you gain the knowledge necessary to understand the algorithms. With calculus you gain the basis to understand optimization theory and how it changes certain parameters of the fundamental algorithms to minimize/maximize a certain objective.</p>
<h3 id="heading-simple-optimization-techniques-how-machines-learn-step-by-step">Simple Optimization Techniques: How Machines Learn Step by Step</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765002727335/a265939c-dea8-4763-8861-7c7a0dbe1081.jpeg" alt="Image of a Star Wars blue and white robot" style="display:block;margin:0 auto" width="4608" height="3072" loading="lazy">

<p><a href="https://www.pexels.com/photo/star-wars-r2-d2-2085831/">Photo by LJ Checo</a></p>
<p>Now, we’re going to see examples of machine learning algorithms used for optimization and deconstruct them so that you can understand how these areas of mathematics apply to them.</p>
<p>In each example, I will explain their main idea with an analogy as well as how each math area is used in each algorithm.</p>
<h4 id="heading-linear-regression">Linear Regression</h4>
<p>Imagine that you are solving a puzzle. To complete the puzzle, you need to arrange the pieces in the right design/order.</p>
<p>The same idea applies to linear regression.</p>
<p>We have matrices (linear algebra) that represent the parameters of the linear regression model and the data that flow into it.</p>
<p>And we can see over time how well the line is fitting the numbers, as well as its error (probabilities and statistics).</p>
<p>To find the best line for the linear regression, we need to know how much the parameters of the model need to change (calculus) and actually apply that change to the parameters (optimization theory).</p>
<p>This way, calculus tells us which direction to change the parameters, and optimization theory tells us how much to actually change them.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764295886800/0c5efd95-9368-4b68-b945-ff911632ca4c.gif" alt="GIF animation of linear regression working over many iterations" style="display:block;margin:0 auto" width="1037" height="856" loading="lazy">

<p>Let’s see how to code the linear regression above:</p>
<pre><code class="language-python">import numpy as np

np.random.seed(42)
X = np.linspace(0, 10, 50)
y_true = 3 * X + 2
noise = np.random.normal(0, 2, 50)
y = y_true + noise

w = 0.1 
b = 0.5
learning_rate = 0.01
iterations = [0, 1, 2, 3, 4, 5]
saved_states = []

for epoch in range(max(iterations) + 1):
    y_pred = w * X + b
    error = np.mean((y - y_pred) ** 2)
    
    if epoch in iterations:
        saved_states.append({
            'epoch': epoch,
            'w': w,
            'b': b,
            'y_pred': y_pred.copy(),
            'error': error
        })
    
    dw = -2 * np.mean(X * (y - y_pred))
    db = -2 * np.mean(y - y_pred)
    
    w = w - learning_rate * dw
    b = b - learning_rate * db
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765335029715/f77be0d9-ea3d-48f1-8cb5-f4806d1295e6.png" alt="Linear regression code example - full code example" style="display:block;margin:0 auto" width="2080" height="3272" loading="lazy">

<p>Let’s see the code block by block:</p>
<p><strong>Import library:</strong></p>
<pre><code class="language-plaintext">import numpy as np
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765335026504/94989760-bb16-4469-947e-eba7bd25b5be.png" alt="Linear regression code example - Import library" style="display:block;margin:0 auto" width="2080" height="528" loading="lazy">

<p>For this problem, we’ll import one of the most used Python libraries: NumPy (which we’ve worked with earlier in the book).</p>
<p><strong>Create data points:</strong></p>
<pre><code class="language-python">np.random.seed(42)
X = np.linspace(0, 10, 50)
y_true = 3 * X + 2
noise = np.random.normal(0, 2, 50)
y = y_true + noise
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765335038511/59e01c3d-27bf-4e6c-8500-9178f1ff569f.png" alt="Linear regression code example - Create data points" style="display:block;margin:0 auto" width="2080" height="844" loading="lazy">

<p>In this code, we define a base line that will help in generating the data points:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765336338665/caa859d0-92cb-424e-8eb2-292093c24355.png" alt="Linear regression code example - image of green base line that will help in generating the data points" style="display:block;margin:0 auto" width="753" height="565" loading="lazy">

<pre><code class="language-python">X = np.linspace(0, 10, 50)
y_true = 3 * X + 2
</code></pre>
<p>After this green line has been created, we will add noise to it to create the data points:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765336395290/80849617-9489-471d-88f6-fb2aaea5b385.png" alt="Linear regression code example - image of a green baseline that will help in generating the data points with blue dots added by introduced noise" style="display:block;margin:0 auto" width="756" height="580" loading="lazy">

<pre><code class="language-plaintext">noise = np.random.normal(0, 2, 50)
y = y_true + noise
</code></pre>
<p>This is how we defined the data points for the line dataset.</p>
<p><strong>Initializing linear regression parameters and others:</strong></p>
<pre><code class="language-python">w = 0.1 
b = 0.5
learning_rate = 0.01
iterations = [0, 1, 2, 3, 4, 5]
saved_states = []
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765335044810/72a775ee-9929-488d-b05e-ab5d32d6b031.png" alt="Linear regression code example - Initializing linear regression parameters and others" style="display:block;margin:0 auto" width="2080" height="844" loading="lazy">

<p>In this block of code, we initialize:</p>
<ul>
<li><p>Linear regression parameters: Weight to be 0.1 and bias to be 0.5</p>
</li>
<li><p>One hyperparameter: Learning rate</p>
</li>
<li><p>How many iterations we are going to use to improve the linear regression</p>
</li>
<li><p>An array called saved_states to store values to later create graphs</p>
</li>
</ul>
<p>This way, we start with this red line:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765336283612/d7bb34b5-aefc-4565-bed2-d2819bc449df.png" alt="Linear regression code example - initializing linear regression parameters and line to fit data points starting with near zero slope" style="display:block;margin:0 auto" width="735" height="575" loading="lazy">

<p><strong>Making the linear regression learn with the data:</strong></p>
<pre><code class="language-python">for epoch in range(max(iterations) + 1):
    y_pred = w * X + b
    error = np.mean((y - y_pred) ** 2)
    
    if epoch in iterations:
        saved_states.append({
            'epoch': epoch,
            'w': w,
            'b': b,
            'y_pred': y_pred.copy(),
            'error': error
        })
    
    dw = -2 * np.mean(X * (y - y_pred))
    db = -2 * np.mean(y - y_pred)
    
    w = w - learning_rate * dw
    b = b - learning_rate * db
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765335055978/2395671a-d873-4bd1-bfa0-349cc6c7be65.png" alt="Linear regression code example - Making the linear regression learn with the data" style="display:block;margin:0 auto" width="2080" height="2012" loading="lazy">

<p>It may appear complicated, but let’s see in smaller blocks:</p>
<ul>
<li>For loop</li>
</ul>
<pre><code class="language-python">for epoch in range(max(iterations) + 1):
</code></pre>
<ul>
<li>Making an prediction and seeing its error</li>
</ul>
<pre><code class="language-python">y_pred = w * X + b
error = np.mean((y - y_pred) ** 2)
</code></pre>
<p>In this block of the code, we find the values predicted for the current parameters and see its error from the real values.</p>
<ul>
<li>Saving current iteration values for future statistics</li>
</ul>
<pre><code class="language-plaintext">if epoch in iterations:
     saved_states.append({
         'epoch': epoch,
         'w': w,
         'b': b,
         'y_pred': y_pred.copy(),
         'error': error
     })
</code></pre>
<p>Here we are juts storing in the saved_states array the values of the current iteration to later compute images.</p>
<ul>
<li>Finding the gradients</li>
</ul>
<pre><code class="language-plaintext">dw = -2 * np.mean(X * (y - y_pred))
db = -2 * np.mean(y - y_pred)
</code></pre>
<p>In this block of code, we find the gradients values for the current prediction.</p>
<p>In other words, for the weight and bias, we find out how much they need to change in order to approximate better the values of the parameters to the data points.</p>
<ul>
<li>Updating the parameters values</li>
</ul>
<pre><code class="language-plaintext">w = w - learning_rate * dw
b = b - learning_rate * db
</code></pre>
<p>Finally, we update the weight and the bias with the new values so that the line better approximates the data points:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765335279159/97e4914a-ed8a-4cf7-8155-e7cde0fa7edd.gif" alt="GIF animation of linear regression working over many iterations" style="display:block;margin:0 auto" width="1037" height="856" loading="lazy">

<h4 id="heading-neural-networks">Neural Networks</h4>
<p>The same puzzle idea applies to neural networks. Neural networks are algorithmic models inspired by the brain that learn patterns from data. They are part of a machine learning field called deep learning, which uses neural networks to learn complex patterns.</p>
<p>Neural networks are important because they power modern AI applications like:</p>
<ul>
<li><p>Image recognition</p>
</li>
<li><p>Language translation</p>
</li>
<li><p>Chatbots</p>
</li>
</ul>
<p>For example, ChatGPT means Chat Generative Pre-trained Transformer. A transformer is an architecture of neural networks.</p>
<p>If you understand neural networks, you’ll understand the foundations that make ChatGPT work.</p>
<ul>
<li><p>We have matrices (linear algebra) that represent the parameters of the neural network model and the data that flow into it.</p>
</li>
<li><p>And we can know over time how well the neural network model is converging to the dataset, fitting the numbers, and see its error (probabilities and statistics).</p>
</li>
<li><p>Calculus will tell us in which direction the parameters of the neural network need to change.</p>
</li>
<li><p>Optimization theory will tell us how much they need to change.</p>
</li>
</ul>
<p>For example, this is a neural network:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1764296443948/e1f46e04-d508-407c-8da6-de8e267a2ba7.png" alt="Image example of a simple neural network" style="display:block;margin:0 auto" width="655" height="391" loading="lazy">

<p>This model has in total 13 parameters:</p>
<ul>
<li><p>It has 10 lines(connections between circles). These are called weights.</p>
</li>
<li><p>It has 2 circles in the hidden layer and 1 in the output layer. Each circle has one bias.</p>
</li>
</ul>
<p><strong>Big question:</strong></p>
<p>Imagine you work in a bank. You are in charge of deciding who gets credit cards or not. For that, you create the neural network above that takes 4 inputs:</p>
<ul>
<li><p>Income</p>
</li>
<li><p>Credit score</p>
</li>
<li><p>Debt ratio</p>
</li>
<li><p>Bankruptcy history</p>
</li>
</ul>
<p>With this neural network well optimized, you can figure it out!</p>
<p>Very simply, without going into things like activation functions, the network processes the 4 inputs through its weights and biases.</p>
<p>Each connection multiplies the input by its weight. After that, each node adds its bias.</p>
<p>The final output is a number between 0 and 1:</p>
<ul>
<li><p>Numbers close to 0 mean "Not approved"</p>
</li>
<li><p>Numbers close to 1 mean "Approved"</p>
</li>
</ul>
<p>For example, a high income figure, a good credit score, and no bankruptcy history data flow through the neural networks and produce 0.92. This means that it should be approved.</p>
<p>But a low income figure with a history of bankruptcy may produce 0.15, which results in a not approved.</p>
<p>In reality, bank systems and others have neural networks that take far more well-chosen parameters and decide this automatically.</p>
<p>This is precisely how AI can be used for credit approval.</p>
<p>But a question remains: What is the best way to know how much the parameters need to change?</p>
<p>In the next part, we are going to see the most famous optimization theory algorithm that will help us decide that.</p>
<h3 id="heading-what-is-adam-the-most-popular-way-ai-models-finds-the-best-learning-path">What is Adam? The Most Popular Way AI Models Finds the Best Learning Path</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766902926221/0b6fbbee-dfda-4a55-bd5d-21215ea33074.jpeg" alt="Image of a mountain" style="display:block;margin:0 auto" width="6000" height="4000" loading="lazy">

<p><a href="https://www.pexels.com/photo/green-leafed-trees-during-fog-time-167684/">Photo by Lum3n</a></p>
<p>To optimize neural network based AI models, one of the most popular methods is called Adam, which means Adaptive Moment Estimation.</p>
<p>The paper that introduced the method is one of the most influential in the 21st century in machine learning, with thousands of citations. As with all ideas in non-symbolic AI, Adam is a mixture of different math concepts.</p>
<p>It's composed of the ideas of two other optimization methods:</p>
<ul>
<li><p>Momentum Gradient Descent: Accumulates velocity from previous gradients to move faster in consistent directions</p>
</li>
<li><p>Root Mean Square Propagation (RMSProp): Adapts learning rates based on recent gradient magnitudes</p>
</li>
</ul>
<p><strong>Let's understand them with an analogy.</strong></p>
<p>Imagine that you are riding a bicycle down a mountain little by little. You already know the direction thanks to calculus.</p>
<p>But how do you descend safely without losing control or going too slowly?</p>
<p>First, you need to build up speed gradually using past momentum. This is one of the main ideas of momentum gradient descent.</p>
<p>It's also important that you adjust your speed based on the terrain's elevation. This is the main idea of RMSProp.</p>
<p>This way, you can safely accelerate and brake appropriately.</p>
<p>When optimizing a model with Adam, this is the same concept. With Adam, we want to optimize a model in a fast and stable way.</p>
<p>The momentum gradient descent ensures the fast part, and the RMSProp ensures the secure part.</p>
<p>Nowadays, for LLMs, which once again are just very big neural network models, a variant of Adam called AdamW is more often used.</p>
<p>Now, let's build a code example of using Adam.</p>
<h4 id="heading-code-example">Code example:</h4>
<p>Using Adam, we are going to optimize this neural network based on fake data.</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765148552889/28101efb-529f-4828-bb7e-adfbf5202d7f.png" alt="Image of a neural network" style="display:block;margin:0 auto" width="655" height="391" loading="lazy">

<p>It will take 4 features:</p>
<ul>
<li><p>Income</p>
</li>
<li><p>Credit score</p>
</li>
<li><p>Debt ratio</p>
</li>
<li><p>Bankruptcy history</p>
</li>
</ul>
<p>And it will tell us if we should or should not approve credit for a given person.</p>
<p>Also, since this book is an introduction to the math of AI, I will not, in this code example, discuss hyperparameter optimization, regularization techniques, and other more advanced topics and good practices.</p>
<p>I want to show why this neural network fails with this data and explain the importance of using great data.</p>
<p>Here is the whole code (and we’ll see each part more in-depth below):</p>
<pre><code class="language-python">import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import TensorDataset, DataLoader, random_split
import pytorch_lightning as pl
import matplotlib.pyplot as plt

torch.manual_seed(42)
x = torch.randn(10000, 4)
y = torch.randint(0, 2, (10000, 1)).float()
dataset = TensorDataset(x, y)

train_size = int(0.8 * len(dataset))
val_size = len(dataset) - train_size
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])

train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32)

class CreditApprovalNet(pl.LightningModule):
    def __init__(self):
        super().__init__()
        self.hidden = nn.Linear(4, 2)
        self.relu = nn.ReLU()
        self.output = nn.Linear(2, 1)
        self.sigmoid = nn.Sigmoid()
        self.loss_fn = nn.BCELoss()
        self.train_losses = []
    
    def forward(self, x):
        x = self.relu(self.hidden(x))
        return self.sigmoid(self.output(x))
    
    def training_step(self, batch, batch_idx):
        x, y = batch
        y_pred = self(x)
        loss = self.loss_fn(y_pred, y)
        self.log('train_loss', loss)
        self.train_losses.append(loss.item())
        return loss
    
    def configure_optimizers(self):
        return optim.Adam(self.parameters(), lr=0.0001)

model = CreditApprovalNet()
trainer = pl.Trainer(max_epochs=100, logger=False, enable_checkpointing=False)
trainer.fit(model, train_loader, val_loader)

# 
plt.plot(model.train_losses)
plt.xlabel('Training Step')
plt.ylabel('Loss')
plt.title('Credit Approval Training')
plt.grid(True, alpha=0.3)
plt.show()
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765150336432/8bb2eab8-60a1-4a01-babf-1b5b11d9187a.png" alt="Code example of training a neural network - Full code" style="display:block;margin:0 auto" width="3096" height="5252" loading="lazy">

<p>Now let’s break it down:</p>
<p><strong>Importing libraries:</strong></p>
<pre><code class="language-python">import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import TensorDataset, DataLoader, random_split
import pytorch_lightning as pl
import matplotlib.pyplot as plt
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765151014087/80097a4b-6bf2-4af0-94da-7f929cf35d2c.png" alt="Code example of training a neural network - Importing libraries" style="display:block;margin:0 auto" width="2732" height="932" loading="lazy">

<p>In this block of code, we are importing code from 3 Python libraries:</p>
<ul>
<li><p><a href="https://pytorch.org/">PyTorch</a>: One of the most popular python libraries to create new AI models in AI research</p>
</li>
<li><p><a href="https://lightning.ai/docs/pytorch/stable/">PyTorch Lightning</a>: A PyTorch wrapper that organizes training code and handles repetitive tasks automatically</p>
</li>
<li><p><a href="https://matplotlib.org/">Matplotlib</a>: One of the most popular python libraries to make graphs from data</p>
</li>
</ul>
<p><strong>Creating data:</strong></p>
<pre><code class="language-python">torch.manual_seed(42)
x = torch.randn(10000, 4)
y = torch.randint(0, 2, (10000, 1)).float()
dataset = TensorDataset(x, y)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765151040691/a2405e15-8ed0-4988-8b78-724f1bd60347.png" alt="Code example of training a neural network - creating data" style="display:block;margin:0 auto" width="2080" height="752" loading="lazy">

<p>In this part, we define a seed to make the random numbers reproducible. In other words, when we run the code many times, the same random numbers will be generated.</p>
<p>Next, we will create 10,000 applications for credit with 4 features in X and their approval decisions in y. After that, we unify everything in the dataset variable.</p>
<p>We’ll use TensorDataset because it allows us to have the 4 features and the target paired together. This way, the data does not get mixed up during training.</p>
<p><strong>Dividing data:</strong></p>
<pre><code class="language-python">train_size = int(0.8 * len(dataset))
val_size = len(dataset) - train_size
train_dataset, val_dataset = random_split(dataset, [train_size, val_size])
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765151063358/8325f2eb-3cf9-4900-909d-545637e20608.png" alt="Code example of training a neural network - Dividing data" style="display:block;margin:0 auto" width="2988" height="664" loading="lazy">

<p>In this block of code, we divide the data into a training dataset and a validation dataset.</p>
<p>This way, we have one dataset that’s being used to train and find the parameters while comparing results with the validation dataset.</p>
<p>As we can see, 80% of the data will be training data, and 20% of the data will be validation data.</p>
<p><strong>Loading data:</strong></p>
<pre><code class="language-python">train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
val_loader = DataLoader(val_dataset, batch_size=32)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765151090966/a80b2483-0bc3-4693-9b58-36765e4b2da2.png" alt="Code example of training a neural network - Loading data" style="display:block;margin:0 auto" width="2768" height="572" loading="lazy">

<p>Here, we load the data into data loaders for the AI model to use.</p>
<p>This way, we have the data automatically split into small batches and shuffled. So instead of processing all 10,000 data points, the model will be trained on one batch, improved, then another batch, then improved again, and so forth. That makes training go faster.</p>
<p><strong>Creating AI model and training process:</strong></p>
<pre><code class="language-python">class CreditApprovalNet(pl.LightningModule):
    def __init__(self):
        super().__init__()
        self.hidden = nn.Linear(4, 2)
        self.relu = nn.ReLU()
        self.output = nn.Linear(2, 1)
        self.sigmoid = nn.Sigmoid()
        self.loss_fn = nn.BCELoss()
        self.train_losses = []
    
    def forward(self, x):
        x = self.relu(self.hidden(x))
        return self.sigmoid(self.output(x))
    
    def training_step(self, batch, batch_idx):
        x, y = batch
        y_pred = self(x)
        loss = self.loss_fn(y_pred, y)
        self.log('train_loss', loss)
        self.train_losses.append(loss.item())
        return loss
    
    def configure_optimizers(self):
        return optim.Adam(self.parameters(), lr=0.0001)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765151116959/d75bd178-24bb-4e5d-b043-c504e280f500.png" alt="Code example of training a neural network - Creating AI model and training process" style="display:block;margin:0 auto" width="2296" height="2552" loading="lazy">

<p>This code block appears to be complicated, but let’s see each method block by block:</p>
<ul>
<li><strong>Creating the class with inheritance:</strong></li>
</ul>
<pre><code class="language-python">class CreditApprovalNet(pl.LightningModule):
</code></pre>
<p>This way, in one line, we can import everything we need to define both the model and how it will be trained.</p>
<ul>
<li><strong>init: Builds the model's layers and components:</strong></li>
</ul>
<pre><code class="language-python">    def __init__(self):
        super().__init__()
        self.hidden = nn.Linear(4, 2)
        self.relu = nn.ReLU()
        self.output = nn.Linear(2, 1)
        self.sigmoid = nn.Sigmoid()
        self.loss_fn = nn.BCELoss()
        self.train_losses = []
</code></pre>
<p>In this section of the code, we are defining the architecture of the AI model.</p>
<ul>
<li><strong>forward: Processes input data through the network to make predictions:</strong></li>
</ul>
<pre><code class="language-python">    def forward(self, x):
        x = self.relu(self.hidden(x))
        return self.sigmoid(self.output(x))
</code></pre>
<p>In this part of the code, we are defining how data will flow in the AI model based on the architecture defined.</p>
<ul>
<li><strong>training_step: Calculates loss for each batch during training:</strong></li>
</ul>
<pre><code class="language-python">    def training_step(self, batch, batch_idx):
        x, y = batch
        y_pred = self(x)
        loss = self.loss_fn(y_pred, y)
        self.log('train_loss', loss)
        self.train_losses.append(loss.item())
        return loss
</code></pre>
<p>Here, we are defining how the model will be trained. In other words, how we will find the best parameters for the model to predict well.</p>
<ul>
<li><strong>configure_optimizers: Sets the Adam optimizer with learning rate:</strong></li>
</ul>
<pre><code class="language-python">    def configure_optimizers(self):
        return optim.Adam(self.parameters(), lr=0.0001)
</code></pre>
<p>Finally, here we are defining what optimizer we are going to use to, step by step, improve the AI model parameters.</p>
<p><strong>Training AI model:</strong></p>
<pre><code class="language-python">model = CreditApprovalNet()
trainer = pl.Trainer(max_epochs=100, logger=False, enable_checkpointing=False)
trainer.fit(model, train_loader, val_loader)
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765151149824/33cb6ad3-3a5d-4964-ab45-ccfd68cd0521.png" alt="Code example of training a neural network - Training AI model" style="display:block;margin:0 auto" width="3096" height="752" loading="lazy">

<p>In this block of code:</p>
<ul>
<li><p>We create the neural network model in the first line</p>
</li>
<li><p>In the 2nd and 3rd line, we prepare the training settings and train the model for 100 epochs</p>
</li>
</ul>
<p>This way, in the command line, this appears:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765152230535/3a5a6a13-12b1-4f31-8bec-cfbc830510a6.png" alt="Code example of training a neural network - training an AI model - command line showing number of layers and parameters" style="display:block;margin:0 auto" width="602" height="306" loading="lazy">

<p>The PyTorch code is essentially telling us the number of parameters in the AI model!</p>
<p><strong>Seeing results and understanding why they are not good:</strong></p>
<pre><code class="language-python">
plt.plot(model.train_losses)
plt.xlabel('Training Step')
plt.ylabel('Loss')
plt.title('Credit Approval Training')
plt.grid(True, alpha=0.3)
plt.show()
</code></pre>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765151210074/3cbecda5-616e-4c3b-a942-2512f81697a1.png" alt="Code example of seeing results and understanding why they are not good:" style="display:block;margin:0 auto" width="2080" height="1024" loading="lazy">

<p>Using the Matplotlib library, we plot the results:</p>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765152336092/6cfce900-ffb6-449f-9d5d-827ff71735bb.png" alt="Code example of training a neural network - Plot the training done over time." style="display:block;margin:0 auto" width="1536" height="916" loading="lazy">

<p><strong>The AI model is not converging.</strong></p>
<p>We can see that because the loss is nearly 0.7 (70%) over time.</p>
<p>The main reason the model is not converging well is that there is little to no relationship between the 4 features and the target variable.</p>
<p>In other words, we do not have good data.</p>
<p>The code works perfectly, but this shows the <strong>most important rule in machine learning</strong>: when we create an AI model, the MOST IMPORTANT thing is data.</p>
<p>It does not matter if you use a simple linear regression or a neural network based on transformers or whatever. If you do not have high quality data, the model is not going to perform well.</p>
<p>Even if we use a good optimizer, like Adam, it will not solve the data problem.</p>
<p><strong>Next steps: Common beginner mistakes</strong></p>
<p>I also wrote this exact code example to show you something very important: neural networks are not always the best models to use.</p>
<p>This is a very common beginner mistake. You may start with neural networks for everything, when often machine learning methods with little data preprocessing do the job well.</p>
<p>For this type of problem, the solution is to first try machine learning methods instead of going to neural networks.</p>
<p>There are many reasons for this, but the main ones are:</p>
<ul>
<li><p>Machine learning methods are simpler and often quicker to train than neural networks</p>
</li>
<li><p>Machine learning methods are simpler to understand how they make decisions. In other words, we can understand how the machine learning model thought to make a prediction.</p>
</li>
<li><p>With computational learning, we can guess with certain machine learning models how well they will predict in the future and provide theoretical guarantees about their performance.</p>
</li>
</ul>
<p>Another common mistake is not dividing the data.</p>
<p>To simplify, I created only a training and validation division of the data</p>
<p>In a serious project, you should always divide it into 3 parts: training, validation, and testing.</p>
<p>With training, you create the model. With validation, you test the model based on the data it was trained on. With the test dataset part, you compare if the loss of the model is similar to the validation or different. If they are very different, it means that the AI model converged to the validation dataset but not the test dataset.</p>
<p>I challenge you to think further about how you could improve this code and to try to make the synthetic data more correlated in order to improve its quality.</p>
<h3 id="heading-applications-in-ai-and-control-theory-of-optimization-theory">Applications in AI and Control Theory of&nbsp;Optimization Theory</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765002780396/5aaf78bb-a06a-4d09-b681-a604a323d430.jpeg" alt="Image of a robot hand touching a web" style="display:block;margin:0 auto" width="6177" height="4118" loading="lazy">

<p><a href="https://www.pexels.com/photo/robot-pointing-on-a-wall-8386440/">Photo by Tara Winstead</a></p>
<p>Optimization theory serves as the engine behind AI and control systems that shape our lives.</p>
<p>From unlocking your phone with facial recognition to autopilot systems guiding planes, optimization algorithms are constantly at work.</p>
<p>When you ask ChatGPT a question, optimization theory determines the values of billions of parameters during training.</p>
<p>The same is true for all other LLMs like Gemini, Claude, Grok, DeepSeek, and others. All of them contain millions and millions of parameters. The only way to find the best combination of the parameters to achieve a certain objective is with optimization theory.</p>
<p>In control theory, many systems like Model Predictive Control (MPC) and adaptive control systems only work thanks to optimization methods that balance how internal components of the control system should work together</p>
<p>Beyond training neural networks and controlling physical systems, optimization powers recommendation systems, resource allocation, and so many other systems.</p>
<p>Some examples are:</p>
<ul>
<li><p>Netflix movie recommendation system</p>
</li>
<li><p>Spotify's song suggestion system</p>
</li>
<li><p>Google systems to reduce data center cooling costs</p>
</li>
<li><p>Quantitative trading firms high-frequency trading systems</p>
</li>
</ul>
<p>To end this final chapter, I’ll share this:</p>
<p><strong>It is optimization theory that makes math models into AI models that impact the lives of millions worldwide.</strong></p>
<h2 id="heading-conclusion-where-mathematics-and-ai-meet">Conclusion: Where Mathematics and AI Meet</h2>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1765002962447/8cdbc79a-5d9c-406d-bad6-2f2e49566b36.jpeg" alt="Pyramids of Egypt with a camel sitting" style="display:block;margin:0 auto" width="5563" height="3709" loading="lazy">

<p><a href="https://www.pexels.com/photo/a-camel-lying-in-the-ground-on-the-background-of-pyramids-18991572/">Photo by AXP Photography</a></p>
<p>When ancient civilizations first carved numbers into clay tablets, they likely didn’t imagine that these symbols would one day allow humanity to create the scientific, technological, and medical marvels we have today.</p>
<p>Yet here we are.</p>
<p>We’re in an era where mathematical ideas developed over many centuries – even millennia – have converged to create artificial intelligence.</p>
<p>Throughout this book, we've traced a path from the most basic math concepts to the cutting edge of AI. We have seen how:</p>
<ul>
<li><p>Matrices compress complex systems into simple forms</p>
</li>
<li><p>Derivatives measure change</p>
</li>
<li><p>Probability helps us navigate uncertainty</p>
</li>
<li><p>Optimization guides algorithms toward better decisions to learn faster.</p>
</li>
</ul>
<p>We’ve also learned how each math field has helped create tools that are responsible for many of the things we take for granted today.</p>
<h3 id="heading-mathematics-is-the-foundation-of-ai">Mathematics is the Foundation of AI</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766902825228/e14431de-44da-4e26-a646-5d277c16b073.jpeg" alt="Board with an integral equation in it" style="display:block;margin:0 auto" width="5060" height="3358" loading="lazy">

<p><a href="https://www.pexels.com/photo/person-writing-on-white-board-3781338/">Photo by Jeswin Thomas</a></p>
<p>Always remember this: AI is not pure magic or a "being" we don't understand. It’s just the combination of many math ideas working very well together.</p>
<p>When you ask a question of ChatGPT or any other LLM, it generates a response. And in the process of generating that response, there are millions of matrix multiplications happening in seconds.</p>
<p>Or, for example, when a self-driving car decides to stop moving because it’s coming up to a crosswalk, there are a lot of math computations (related to calculus and probability and statistics) working very fast to ensure safety.</p>
<p>The great thing about mathematics is that it’s a common, standard language of logic. No matter the backgrounds of people or where they were born, a derivative will always be a derivative, and the same thing goes for key AI concepts.</p>
<p>This way, scientists and engineers worldwide can improve each other's work because everyone understands the same language.</p>
<h3 id="heading-the-future-on-device-ai-and-the-democratization-of-ai">The Future: On Device AI and the Democratization of AI</h3>
<img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1766902760109/02b3f00d-a8df-4546-bf41-c1791cdc5f18.jpeg" alt="Image of an chip" style="display:block;margin:0 auto" width="4500" height="3000" loading="lazy">

<p><a href="https://www.pexels.com/photo/abstract-image-of-a-microchip-with-heatmap-colors-28767589/">Photo by Steve Johnson</a></p>
<p>One shift happening now is the move toward edge AI. That is, AI that runs locally on your phone, computer, and really in all your devices (rather than in distant data centers).</p>
<p>This way, privacy is guaranteed because it runs locally. Waiting times for AI models decrease because no data needs to be sent. AI can be used offline, and costs decrease.</p>
<p>And what about the massive data centers being built all over the world? Those will be used for more products that will help improve the lives of millions of people.</p>
<p>As AI becomes more local and more processing power is freed up from big data centers, new AI innovations will appear, and more benefits will come.</p>
<p>The same way that in the past century every computer got its own networking chip, every device will have (and in some cases, already has) AI accelerators.</p>
<p>And much of it will be thanks to the math you learned in this book.</p>
<h3 id="heading-final-reflections">Final Reflections</h3>
<p>Isaac Newton wrote, "If I have seen further, it is by standing on the shoulders of giants."</p>
<p>Every algorithm you use, every model you train, and every new theorem you learn stands on centuries of mathematical progress. You now stand on those same shoulders of these giants!</p>
<p>Thank you for reading, and happy learning.</p>
<p>Here’s the full book <a href="https://github.com/tiagomonteiro0715/The-Math-Behind-Artificial-Intelligence-A-Guide-to-AI-Foundations">GitHub repository with all the code</a>.</p>
<h3 id="heading-acknowledgements">Acknowledgements</h3>
<p>First and foremost, I would like to thank <a href="https://www.linkedin.com/in/guilherme-mendes-a416b7206/"><strong>Guilherme Mendes</strong></a>, currently a Master’s student in Electrical and Computer Engineering at NOVA University, specializing in Control Theory, for reviewing the mathematical and technical details of the 1st version of this book.</p>
<p>I am also grateful to the organizations that gave me opportunities to grow:</p>
<ul>
<li><p><a href="https://www.fct.unl.pt/en">NOVA School of Science and Technology</a></p>
</li>
<li><p><a href="https://ieee-pt.org/">IEEE Portugal Section</a></p>
</li>
<li><p><a href="https://www.siliconvalleyfellowship.com/">Silicon Valley Fellowship</a></p>
</li>
<li><p><a href="https://www.northeastern.edu/">Northeastern University</a></p>
</li>
<li><p><a href="https://best.eu.org/index.jsp">BEST and BEST Almada</a></p>
</li>
<li><p><a href="https://magmastudio.pt/">Magma Studio</a></p>
</li>
</ul>
<p>A special thank you goes to the freeCodeCamp editorial team**,** especially Abigail Rennemeyer, for their patience and for reviewing every chapter of this book.</p>
<p>I would also like to thank all the professors at NOVA FCT who have taught and guided me throughout my academic journey, especially those from the Department of Electrical and Computer Engineering.</p>
<h2 id="heading-about-the-author">About the Author</h2>
<ul>
<li><p>LinkedIn: <a href="https://www.linkedin.com/in/tiago-monteiro-/">https://www.linkedin.com/in/tiago-monteiro-</a></p>
</li>
<li><p>GitHub: <a href="https://github.com/tiagomonteiro0715">https://github.com/tiagomonteiro0715</a></p>
</li>
<li><p>Email: <a href="mailto:monteiro.t@northeastern.edu">monteiro.t@northeastern.edu</a></p>
</li>
</ul>
<p>My name is Tiago Monteiro, and I’m now pursuing a master's degree in Artificial Intelligence at Northeastern University in the Silicon Valley Campus (San Jose) on a merit-based scholarship.</p>
<p>I’m not from the United States. I am a Portuguese national, born and raised in the district of Lisbon.</p>
<p>In Portugal, I completed a bachelor's degree in electrical and computer engineering at NOVA University, one of Portugal's best universities.</p>
<p>I have authored over 20 articles for freeCodeCamp, which have accumulated more than 240,000 views over the years, and completed the Deep Learning Specialization from DeepLearningAI, taught by Andrew Ng.</p>
<p>Also, I had the privilege of participating in the winter 2025 batch of the renowned Silicon Valley Fellowship program.</p>
<h4 id="heading-why-did-i-choose-electrical-and-computer-engineering">Why did I choose electrical and computer engineering?</h4>
<p>After finishing the Portuguese national math exam in 12th grade, I chose Electrical and Computer Engineering (ECE) to challenge myself and learn new math on my own.</p>
<p>The ECE degree combined:</p>
<ul>
<li><p>Advanced Mathematics</p>
</li>
<li><p>Programming (from Assembly to Python)</p>
</li>
<li><p>Physics (classical mechanics, electromagnetism)</p>
</li>
</ul>
<h4 id="heading-what-did-i-gain-exactly">What did I gain exactly?</h4>
<p>I mastered the skills needed to quickly understand AI research, particularly after completing Andrew Ng's Deep Learning Specialization.</p>
<p>In Portugal, I also studied advanced STEM areas including, for example:</p>
<ul>
<li><p><strong>Partial Differential Equations</strong> for modeling real-world phenomena</p>
</li>
<li><p><strong>Harmonic analysis</strong> (Fourier/Laplace transforms) for signal processing and alternative problem perspectives</p>
</li>
<li><p><strong>Complex analysis</strong> involving derivatives and integrals in the complex domain</p>
</li>
<li><p><strong>Numerical methods</strong> for approximating mathematical solutions computationally</p>
</li>
<li><p><strong>Signal/control theory</strong> for ensuring system stability in dynamic environments</p>
</li>
<li><p><strong>Physics classes</strong> in classical mechanics and electromagnetism fundamentals</p>
</li>
</ul>
<p>While not directly applied to AI, these studies enhanced my systems thinking and ability to independently learn complex STEM concepts.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Design Structured Database Systems Using SQL [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ This book will guide you, step-by-step, through designing a relational database using SQL. SQL is one of the most recognized relational languages for managing and querying data in databases. You’ll learn the fundamental concepts related to both data ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-design-structured-database-systems-using-sql-full-book/</link>
                <guid isPermaLink="false">689cd35e34fbf8c230ae0b6c</guid>
                
                    <category>
                        <![CDATA[ SQL ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Databases ]]>
                    </category>
                
                    <category>
                        <![CDATA[ database design ]]>
                    </category>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Daniel García Solla ]]>
                </dc:creator>
                <pubDate>Wed, 13 Aug 2025 18:03:10 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1755095979245/dfd39c26-3456-4e79-a01c-0b2a82f7a034.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>This book will guide you, step-by-step, through designing a relational database using SQL. SQL is one of the most recognized relational languages for managing and querying data in databases.</p>
<p>You’ll learn the fundamental concepts related to both data and the databases where they are stored and managed – from how data is transformed into information and subsequently into knowledge, to the architecture of a database management system (DBMS). We’ll also cover the different stages of the database design process, as well as its key principles, focusing specifically on the design of relational databases.</p>
<p>By the end of the book, you’ll have a solid understanding of how to design and maintain efficient, secure databases that can support complex data-driven applications, all aimed at meeting a series of requirements imposed by end users or clients. You’ll also learn the SQL fundamentals you’ll need to implement this design on a DBMS, and then maintain and query data on it.</p>
<p>So, whether you're a beginner or looking to enhance your skills, this book will provide the knowledge and tools you need to succeed in the world of data management.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-prerequisites">Prerequisites</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-role-of-data-in-todays-digital-world">The Role of Data in Today's Digital World</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-1-what-is-data">Chapter 1: What is Data?</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-dikw-pyramid">DIKW Pyramid</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-2-what-is-a-database">Chapter 2: What is a Database?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-dmbs-database-management-systems">DMBS (Database Management Systems)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-acid-properties-and-transactional-dbms">ACID Properties and Transactional DBMS</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-database-management-system-architecture">Database Management System Architecture</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-3-data-management-models-and-technologies">Chapter 3: Data Management Models and Technologies</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-types-of-data-according-to-structure">Types of Data According to Structure</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-big-data">Big Data</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-nosql-databases">NoSQL Databases</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-data-warehousing">Data Warehousing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-data-lakes">Data Lakes</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-semantic-web">Semantic Web</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-4-database-design">Chapter 4: Database Design</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-database-design-levels">Database Design Levels</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-5-relational-model-structured-data">Chapter 5: Relational Model (Structured Data)</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-table-relation">Table (Relation)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-schema">Schema</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tuple">Tuple</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-attribute-domain">Attribute Domain</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-derived-attribute">Derived attribute</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conceptual-representation">Conceptual Representation</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-repeating-group">Repeating Group</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-data-inconsistency">Data Inconsistency</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-entity-associations">Entity Associations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-generalization-and-specialization">Generalization and Specialization</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-entity-association-pitfalls">Entity Association Pitfalls</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-keys">Keys</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-weak-entities">Weak Entities</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-navigability">Navigability</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-constraints">Constraints</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-data-integrity">Data Integrity</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-integrity-constraints">Integrity Constraints</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-6-relational-schema-diagram">Chapter 6: Relational Schema Diagram</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-1-association">1-1 association</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-1-m-association">1-M association</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-minimum-cardinality-issues">Minimum cardinality issues</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-n-m-association">N-M association</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-is-a-hierarchy">IS-A Hierarchy</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-7-normalization">Chapter 7: Normalization</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-decomposition">Decomposition</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-functional-dependency">Functional dependency</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-normal-forms">Normal forms</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-bcnf">BCNF</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-other-normal-forms">Other normal forms</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-8-query-languages">Chapter 8: Query Languages</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-formal-vs-practical-query-languages">Formal vs practical query languages</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-9-sql-structured-query-language">Chapter 9: SQL (Structured Query Language)</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-ddl">DDL</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-dcl">DCL</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-dml">DML</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-views">Views</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-database-administration">Database Administration</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-10-database-design-process-example">Chapter 10: Database Design Process Example</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-entity-relation-to-logical-model">Entity-relation to logical model</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-create-the-database">How to create the database</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-11-example-queries">Chapter 11: Example Queries</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-tuple-filtering">Tuple filtering</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-subqueries">Subqueries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-common-table-expressions">Common table expressions</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-set-operations">Set operations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-aggregation-queries">Aggregation queries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-division-queries">Division queries</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-ranking-queries">Ranking queries</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-prerequisites">Prerequisites:</h2>
<p>Before going through this book, there are a few useful prerequisites you should have:</p>
<h3 id="heading-fundamentals">Fundamentals:</h3>
<ol>
<li><p>Basic programming knowledge like variables, data types (string/number/boolean), and conditionals/loops</p>
</li>
<li><p>Familiarity with spreadsheet terms/basic functions (rows, columns, sorting/filtering) as this will help map to tables/tuples/attributes</p>
</li>
<li><p>Command-line basics like how to open a terminal, run a command, set PATH (you’ll use CLI tools occasionally here), and so on</p>
</li>
</ol>
<h3 id="heading-environment-to-set-up">Environment to set up</h3>
<ol>
<li><p>A relational DBMS like PostgreSQL (recommended, as it’s what we’ll use here)</p>
</li>
<li><p>A SQL client like psql, pgAdmin, TablePlus, or DBeaver (pick one)</p>
</li>
<li><p>An Entity Relationship Diagram tool like <a target="_blank" href="http://draw.io/diagrams.net">draw.io/diagrams.net</a>, Lucidchart, or <a target="_blank" href="http://dbdiagram.io">dbdiagram.io</a></p>
</li>
<li><p>A code editor like VS Code (with SQL and ERD extensions is fine)</p>
</li>
</ol>
<h3 id="heading-helpful-background">Helpful background</h3>
<ol>
<li><p>Familiarity with some math/logic basics like sets/subsets, relations, functions as well as basic propositional logic (AND/OR/NOT, implication).</p>
</li>
<li><p>Basic knowledge of data modeling terms (entity, attribute, relationship, cardinality, and so on)</p>
</li>
<li><p>Version control basics</p>
</li>
</ol>
<p>With that sorted, let’s dive in.</p>
<h2 id="heading-the-role-of-data-in-todays-digital-world">The Role of Data in Today's Digital World</h2>
<p>These days, every action we take on the internet leaves behind a trail of information or data – whether it's conducting a bank transaction or shopping online.</p>
<p>But you may sometimes wonder whether it actually makes sense for these digital actions to be recorded. Do we need records of keystrokes when using a keyboard app, images saved in a gallery app, files in a file management program, notes saved in a note-taking app, or even vehicle routes with integrated Android Auto technology?</p>
<p>Some of these actions may not seem particularly useful at first, but they help developers and designers provide better, more advanced, and efficient services to users.</p>
<p>For instance, understanding how a user types on a keyboard app can improve the real-time typing experience by adapting the internal dictionary to the user's typing style and correcting errors more effectively. It also improves gesture typing, a feature based on artificial intelligence techniques that requires a large number of examples to be deployed successfully on a product.</p>
<p>Similarly, simple images saved in a gallery may not seem significant enough to be recorded on external sites, or even registered at all.</p>
<p>Image files, for example, can contain <a target="_blank" href="https://en.wikipedia.org/wiki/Exif"><strong>EXIF metadata</strong></a> with information about the image, such as the location where it was captured, the date of creation, its resolution, orientation, and the camera model used – among other data. While a user may not be interested in this data, it serves as the foundation for various application services, including classifying images into albums based on location, creating visual timelines, and generating "memories." These features significantly enhance the user experience.</p>
<p>Besides metadata, the content of images also creates a "digital trail" on third-party servers, which might initially seem intrusive and not beneficial to the user. However, it can lead to enhanced services. Since these third parties have the resources to train large machine learning models, they can recognize objects and faces in images. This improves album classification and allows users to search through images using text. Third parties can also identify which people or items are in a photo and link their data with other services.</p>
<p>Regarding the data generated by smart vehicles or <a target="_blank" href="https://www.ibm.com/think/insights/how-modern-enterprises-are-using-iot-data-to-spur-innovation"><strong>IoT devices</strong></a> in general, the purpose is fundamentally the same: to provide users with better services, such as route optimization, maintenance prediction, prevention of possible failures, driving assistance, and integration with other smart devices in the environment.</p>
<p>These features are implemented using artificial intelligence techniques that learn from examples. Typically, the more data available, the better the underlying models "learn," leading to better results.</p>
<p>Ultimately, regardless of the legal and privacy issues related to these practices, recording what we do is not an end in itself. Rather, it’s a means of turning scattered information into useful knowledge, which can then be used to create services that enhance our productivity or user experience.</p>
<p>One clear example of this is in this very article on the <a target="_blank" href="https://hashnode.com/changelog/free-ai-for-all-users-blogging?source=changelogs"><strong>Hashnode platform</strong></a>. It provides writers with translation, rewriting, and keyword optimization services for <a target="_blank" href="https://developers.google.com/search/docs/fundamentals/seo-starter-guide?hl=en"><strong>SEO searches</strong></a>, all of which are based on artificial intelligence models that have been trained using large amounts of text – that is, data.</p>
<p>So to make sure this is all technically feasible, we had to develop specific techniques for collecting, storing, and managing information securely, efficiently, and consistently.</p>
<ul>
<li><p>Collection involves capturing information from various sources, such as IoT sensors, mobile devices, and social interactions, either manually or automatically.</p>
</li>
<li><p>This information can then be stored and accessed again when we need to transform it or apply processes that improve query efficiency or reduce storage space. This is precisely why data compression is a critical aspect of data storage.</p>
</li>
<li><p>Lastly, data management involves organizational, protective, governance, and analytical tasks.</p>
</li>
</ul>
<p>In this book, we will focus on storage, which is the key aspect handled by databases. But databases are used for more than just storing and accessing data, as we will see later. They also provide a set of functionalities that allow us to organize, protect, and ensure the integrity of data, as well as to query it efficiently and concurrently.</p>
<p>This makes databases a fundamental component of the infrastructure for these services, which are often offered to a large number of users.</p>
<p>More precisely, we will focus on explaining all the necessary theoretical concepts you need to know to design and maintain a database. There are many ways to store data, depending on its nature or the client's needs, but we will focus on one specific structure.</p>
<p>To grasp the fundamentals of storing and managing data, we should begin with the most straightforward cases, which involve the simplest possible data structures. You’ll also learn the <strong>SQL</strong> language and its relevance to database maintenance through examples.</p>
<h2 id="heading-chapter-1-what-is-data">Chapter 1: What is Data?</h2>
<p>Before we start working with databases, it's helpful to have a clear understanding of what data is. More specifically, we need to understand what data means in the context of working with databases and SQL.</p>
<p>The official <a target="_blank" href="https://en.wikipedia.org/wiki/Data"><strong>definition of data</strong></a> covers the most basic level, which states that data is a symbolic representation of a quantitative or qualitative attribute or variable that describes an empirical fact, event, or entity.</p>
<p>It's important to note that data has no inherent meaning. In other words, data is merely a value representing something observable or measurable – it doesn't provide any interpretable meaning.</p>
<p>For instance, the number 27 is data to which we initially can't provide meaning, though we can store, transform, compress, and encrypt it, and so on, if possible. Later, if we discover that this value stems from a variable representing temperatures, then we have more than just data – we have semantics, or meaning.</p>
<p>In this example, the number 27 is considered raw data. <a target="_blank" href="https://www.lenovo.com/ca/en/glossary/raw-data/"><strong>Raw data</strong></a> is data that has been collected from a source, yet it lacks meaning or <a target="_blank" href="https://en.wikipedia.org/wiki/Semantic_data_model"><strong>semantics</strong></a> and has not been processed or organized.</p>
<p>In the context of databases, the term <strong>variable</strong> is occasionally used to denote the origin of the data. But the term <strong>attribute</strong> is more common, as we will see later. So to sum up, an attribute can be viewed as a variable in programming. It represents a feature of an entity, such as a person's age. It’s characterized by a data type and a domain that define what the values can be and what its possible values are, respectively.</p>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Data_type">Data types</a> are the internal formats and operations supported by an attribute's data. They can include:</p>
<ul>
<li><p>integers (<strong>ints</strong>), which are typically encoded in computer science as 32-bit sequences</p>
</li>
<li><p>text strings encoded in <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Glossary/UTF-8"><strong>UTF-8</strong></a> format</p>
</li>
<li><p>decimal numbers (floats or doubles, among others), represented using the <a target="_blank" href="https://learn.microsoft.com/en-us/cpp/build/ieee-floating-point-representation?view=msvc-170"><strong>IEEE-754</strong></a> floating-point standard, and</p>
</li>
<li><p>boolean values that can be true or false and are encoded with bits as 0 or 1.</p>
</li>
</ul>
<p>As you can see, the <strong>data type</strong> defines how an attribute's values can be, while the <a target="_blank" href="https://en.wikipedia.org/wiki/Attribute_domain"><strong>domain</strong></a> is a set containing all the acceptable attribute values. A domain consists of a data type that limits the form of the data and a series of constraints that restrict the possible values that can be instantiated within that base data type.</p>
<p>For instance, if an attribute is labeled as an integer and represents a person's age, it's evident that the domain can’t contain negative numbers, despite the int data type allowing them. Consequently, the domain can be defined as all possible integer values with additional constraints ensuring that values less than zero aren’t considered, leaving only the positive integers needed.</p>
<p>Through these concepts, we can understand data in its most basic form. If we take a decimal number like 3.24, it may indicate a measurement for scientific purposes. A text string like "Juan", on the other hand, may represent a person's name. In other words, the semantics of a sequence of characters define its meaning. Alone, the sequence of characters doesn't represent anything – but together, they can represent a Spanish text with a meaning, such as someone's name.</p>
<p>Beyond atomic data, which are the most basic elements that can contain information, there’s also much more complex data out there. This includes document data, spatial and geographic data, network or graph data, and multidimensional data. The only difference between the "atomic" data we saw earlier and these complex forms of data is that the latter are composed of relationships or <strong>associations</strong> between simpler data.</p>
<p>For instance, a document consists of sequences of characters (strings) related to each other, where one string might represent the title and another a paragraph. In a computer network modeled as a graph, there could be IP addresses at the nodes, which we can think of as encoded strings, and references to other nodes, which are also IP addresses.</p>
<p>We won't delve into the complex nature of such data here because it’s managed by specialized databases that are more difficult to understand, and where SQL is not always present.</p>
<h3 id="heading-dikw-pyramid">DIKW Pyramid</h3>
<p>So far, we’ve seen that data itself is just 'symbols' that can be stored, with no inherent meaning unless their origin or interpretation is known.</p>
<p>But it’s also possible to train machine learning models to provide services that appear much more complex compared to the data they were built with. In other words, we can build complex information systems from raw data that contain <strong>higher-level</strong> knowledge than the data we have discussed.</p>
<p>The <a target="_blank" href="https://www.datacamp.com/cheat-sheet/the-data-information-knowledge-wisdom-pyramid"><strong>DIKW (Data, Information, Knowledge, Wisdom) pyramid</strong></a> models this transformation from data to knowledge, establishing a hierarchy through which we can acquire knowledge about some aspect of reality based on data. To understand this, let’s look at the four levels of knowledge organization.</p>
<ol>
<li><p><strong>Data:</strong> At this level, our knowledge of the world – or rather, what we know about it – is represented as raw data. As previously mentioned, raw data is devoid of semantics. The only options here are to store and analyze the data. Although they don't explicitly provide high-level knowledge, we can clean the data to avoid missing or corrupt values and calculate statistical measures.</p>
<p> <strong>Example:</strong> As before, a raw value, such as the integer 27, is data from which we can only calculate certain statistical metrics. We can’t interpret it because we don't know its meaning until we get more context.</p>
</li>
<li><p><strong>Information:</strong> After advancing from the previous level, the raw data is provided with semantics, which offers meaning to the stored and analyzed values. Now, the data is better organized because it’s contextualized with respect to its semantics.</p>
<p> This is the primary feature of this level, though certain relationships between the data also allow for more complex statistics to be calculated and more valuable questions to be answered about the data. The knowledge at this level is more abstract and valuable than the previous one.</p>
<p> <strong>Example:</strong> Continuing with the previous example, the number 27 could represent a person's age. So, here we can interpret and organize it with deeper comprehension and analyze it more precisely.</p>
</li>
<li><p><strong>Knowledge:</strong> At this point, knowledge resides in models that capture the patterns of the analyzed and organized data according to their semantics. That is, data follow hidden patterns that aren’t easily discernible, but can be revealed through advanced statistical techniques or machine learning.</p>
<p> So, at this level, information is compressed and summarized, or rather, an understanding of it’s generated through a model, allowing it to be synthesized.</p>
<p> This level is higher than the previous one because it extracts even more abstract knowledge from the information. Such knowledge describes the data itself, serves to make predictions, and achieves certain outcomes by leveraging the higher-level relationships between the data.</p>
<p> <strong>Example:</strong> Once we have meaningful data, we can build models to describe or summarize it in order to make predictions about unseen data or draw conclusions.</p>
<p> For example, we can use a statistical metric, such as the mean, as a model to determine the average age of a given dataset. Later, by comparing this mean with the ages of other people, we can determine whether they are above or below the average. But the models used to describe data at this stage are usually more complex and practical.</p>
</li>
<li><p><strong>Wisdom:</strong> Building on the knowledge from the previous level, we reach a point where it’s no longer possible to extract higher-level relationships from the data. This means that no further abstraction is possible. The only remaining task is to combine our description of the data from the previous level with a social and ethical context, along with the professional experience of people who intend to use this knowledge to guide strategic decision-making and evaluate its consequences over time.</p>
<p> <strong>Example:</strong> At this final level, we can use a person's age, for which we have models describing them, and combine it with information about the context in which that information was collected to inform strategic decisions.</p>
<p> Note that the data may emerge from an organization, which is the context in which strategic decisions are made. The key point here is that the purpose of having such high-level knowledge is to inform strategic decisions.</p>
</li>
</ol>
<p>By studying this hierarchy, we can see that the interpretation of raw data leads to the acquisition of knowledge, which lets us make informed decisions. Databases help in this process primarily by storing data, which is one of their main objectives. But they also assist us with the analysis process by adapting the data's storage and organization methods.</p>
<p>At this point, you might ask the question: <strong>How do we want the database to store and analyze this data?</strong> First, we need to store the data <a target="_blank" href="https://en.wikipedia.org/wiki/Persistent_memory">persistently</a> in <a target="_blank" href="https://www.geeksforgeeks.org/computer-science-fundamentals/secondary-memory/">secondary memory</a> so that it can be retrieved at any time, rather than in <strong>volatile memory</strong> such as <strong>RAM</strong>.</p>
<p>On the other hand, <strong>analyzing</strong> data involves a wide variety of operations, ranging from simple searches and filtering to complex aggregations, pattern detection, statistical calculations, executing elaborate SQL queries, and processing text or images. Each type of data and operational need requires different algorithms and data structures for efficiency.</p>
<p>This means that since a database must provide functionalities at the storage and analysis layers, you might wonder whether a "general" database system exists that is capable of storing and analyzing data of any kind, regardless of its complexity or user needs. As we will see below, such a general system can’t exist. But there are systems built to handle any type of data-related problem, <strong>as long as the data is in a specific “shape”</strong>.</p>
<h2 id="heading-chapter-2-what-is-a-database">Chapter 2: What is a Database?</h2>
<p>Once you learn about the main functions a database needs to provide, you can understand its advantages and why it exists – especially when compared to trying to implement these functions without a database. To help illustrate this, we’ll start by analyzing a case where we try to solve a problem involving data without a database. This will show the problems that can arise and how they are resolved.</p>
<h3 id="heading-storing-data-without-a-database">Storing Data Without a Database</h3>
<p>In terms of data <strong>storage</strong>, the raw data could be stored directly in binary files in secondary memory. For <strong>analysis</strong>, we can implement a software "layer" which we can label "processing layer,". It contains programs that manipulate the stored data by accessing it and performing transformations based on implemented logic. And to facilitate data manipulation by users, there can be a <strong>graphical interface</strong> component that simplifies the use of these programs.</p>
<p>A practical example will illustrate this better. Suppose we are working with a domain that contains data about people and their financial information. Our objective is to analyze this data and make economic predictions. This data may originate from government sources, surveys, or other information systems. So we’ll need to store it in our system as binary files.</p>
<p>But we’re faced with a couple problems: first, we need to choose the optimal file type. Then we need to choose the best way to represent the data in the file to minimize problems in future stages when designing programs for access and analysis.</p>
<p>For example, storing the data in a <strong>sequential file</strong>, where the data is stored contiguously, is different from storing it in an <strong>indexed file</strong>, where the information is organized by an <a target="_blank" href="https://www.geeksforgeeks.org/dbms/indexing-in-databases-set-1/"><strong>index</strong></a>. In other words, there’s an index that organizes the data by name, so all people whose names (or a similar characteristic) begin with the same letter are stored contiguously in the same block, separated from the remaining letters. This recursive principle continues for the subsequent letters of the name. It's as if the data were sorted alphabetically, though generally, a single level of recursion is enough.</p>
<p><strong>Let’s look at an example:</strong> In a sequential file, people's names are stored in a "disorganized" way, which requires us to search through the entire file to retrieve a specific person's record. In contrast, an indexed file sorts people alphabetically by name. By consulting the index, we can determine where names beginning with a certain letter start, thus avoiding the need to look through the entire file. In other words, the index is similar to the table of contents in a book, which tells us on which page each chapter begins.</p>
<p>This type of decision affects how efficient searches and queries on data are, as well as its processing. Each file type has its own advantages and disadvantages, as you might expect.</p>
<p>Similarly, there is a wide variety of decisions we can consider when designing programs to access and operate on the data. These are directly influenced by the previous decisions. For example, if we change the file type, the software of these programs will most likely need to be reprogrammed. You can think of these programs as Python scripts that automate certain analysis processes.</p>
<p>Also, when we’re implementing these programs, we need to account for details such as <strong>concurrent</strong> access to data, which is difficult to implement from scratch, as well as other security features, such as data encryption, compression, and detecting erroneous or incomplete data. These features are essential to providing a good analysis service, but they are difficult to program and maintain.</p>
<p>In short, without a database, it’s possible to solve the problem of storing and analyzing data – but implementing all the software is potentially quite complicated, especially if we aim to do so from scratch. If we have the right resources, it may be possible to complete this process and end up with a sufficiently efficient system. But in most cases, using a database is more convenient.</p>
<h3 id="heading-storing-data-using-a-database">Storing Data Using a Database</h3>
<p>One way to simplify these processes is to use a database, which is an <strong>organized collection</strong> of data that models a <strong>domain</strong> and provides storage and analytical support for the processes we need to apply to the data. Without a database, data had to be stored in "single files" – but using a database, it’s stored according to a model that defines the type of information and its internal relationships. This is why the definition uses the term "organized."</p>
<p>As for the term "collection," it refers to the idea that a database is a set of data from the same <a target="_blank" href="https://en.wikipedia.org/wiki/Domain_\(software_engineering\)"><strong>domain</strong></a>. Here, by "domain" we mean the problem we are dealing with, for which we need to store and analyze data. In our example above, the domain would be the "universe" of people and all the tax concepts associated with them – that is, the set of concepts and information from the real environment that may be relevant to solve a problem using those data.</p>
<p>The advantages of a database extend beyond just storage. They also include the <strong>normalization</strong> of storage and organization, allowing for efficient <strong>queries</strong> on the stored data. These queries form the basic operations of any analysis process (querying). They’re also the fundamental support for other tasks such as the technical maintenance of the information system, data management, or even features like the system's scalability.</p>
<h3 id="heading-dmbs-database-management-systems">DMBS (Database Management Systems)</h3>
<p>Data management involves a series of additional functionalities that are provided by a component on which the vast majority of databases are currently based: the <a target="_blank" href="https://www.ibm.com/docs/en/zos-basic-skills?topic=zos-what-is-database-management-system"><strong>DBMS (Database Management System)</strong></a>. As its name suggests, this component is a software element responsible for centrally and efficiently managing the entire life cycle of stored data.</p>
<p>In this context, management refers primarily to the storage, extraction, modification, deletion, and search of data. These are the fundamental operations necessary for a database to be considered operational.</p>
<p>But management also involves additional functionalities that are useful in a database:</p>
<ul>
<li><p><strong>Centralization:</strong> Storing all the data in one system avoids having information scattered across many files, which may lead to unnecessary duplication of information, such as data references or the data itself. If the information system is not designed and implemented correctly, this can lead to inconsistencies and errors. But this is not a concern if we use a database.</p>
</li>
<li><p><strong>Data integrity and security:</strong> The management system controls who can access the data through access controls and permissions for different database users. It also ensures data integrity, a topic we will discuss later.</p>
</li>
<li><p><strong>Concurrent access and sharing:</strong> Information systems typically support applications used by many users simultaneously, which causes synchronization issues handled automatically by the DBMS. Fortunately, this means we don't have to implement specific logic in our database to ensure concurrent access to data by many users.</p>
</li>
</ul>
<p>Finally, another feature of DBMSs is that they streamline the development and maintenance of information systems built using databases, especially those that rely on a DBMS. There are many different DBMS software programs, such as MySQL, MariaDB, PostgreSQL, MongoDB, and Neo4j, among others. Here, we will focus on PostgreSQL.</p>
<h3 id="heading-acid-properties-and-transactional-dbms">ACID Properties and Transactional DBMS</h3>
<p>Beyond the basic operations we’ve discussed, it's important to highlight the significance of transactional support in modern DBMSs for applications such as banking, online invoicing, and healthcare.</p>
<p>In these areas, it’s usually essential that any modification or query of the data follow a <a target="_blank" href="https://cloud.google.com/learn/what-are-transactional-databases"><strong>transaction</strong></a> mechanism. In other words, the operations performed on the database must be composed of a block of low-level instructions (reads and writes), and the manager must ensure that these operations are executed as a whole or not at all. This is often called an atomic operation.</p>
<p>This helps prevent technical failures from causing inconsistencies in databases (or similar problems). For example, if a user sends money via internet and an error occurs, the entire transaction is canceled, as if it had never occurred. This protects the database from remaining in an <strong>inconsistent</strong> state, such as when one party has sent money, but the other has not received it. So the DBMS is responsible for ensuring this atomicity in database operations, which requires it to fulfill the <a target="_blank" href="https://www.freecodecamp.org/news/acid-databases-explained/"><strong>ACID properties</strong></a>. They are:</p>
<p><strong>1. Atomicity:</strong> A transaction operates under the "all or nothing" principle, meaning that either all of its low-level instructions are completed, or none of them are executed.</p>
<p>Example: A bank transaction must be completed fully, not left in an intermediate state where one party sends the money and the other does not receive it.</p>
<p><strong>2. Consistency:</strong> Every transaction updates the database, ensuring it remains in a valid state and preserves data integrity.</p>
<p>Example: If a transaction changes a person's age, the final age can’t be negative.</p>
<p><strong>3. Isolation:</strong> Concurrent transactions should not interfere with each other in a way that produces inconsistent results.</p>
<p>Example: Two people try to book the last seat on a flight at the same time. Isolation ensures that only one booking succeeds and the seat isn't double-booked.</p>
<p><strong>4. Durability:</strong> Once a transaction has been completed, its effects are permanent. Even if the system fails, it must be ensured that the changes remain by writing them to persistent storage.</p>
<p>Example: If you transfer money between bank accounts and the system crashes right after, the transfer should still be reflected when the system comes back online.</p>
<p>Finally, it’s important to understand that <strong>not all</strong> database management systems <em>(DBMSs)</em> need to be transactional, although many of them support such functionalities.</p>
<h3 id="heading-database-management-system-architecture">Database Management System Architecture</h3>
<p>After seeing what a DBMS is at a high level, we can examine how its functionalities are implemented in greater detail. We won’t look at the lowest possible level, but rather at the architectural level.</p>
<p>To better understand how a DBMS operates, we can focus on each of its component's roles when receiving a user request, whether it's a data modification, management operation, or data retrieval query.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/8_W5JT7Jz2Y" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<p>Overall, each DBMS is unique, with components specific to its design and needs. Broadly speaking, though, they all share the following components:</p>
<ul>
<li><p><strong>Precompiler</strong>: This component extracts and separates individual language statements embedded in applications based on the user query, which is usually in a language like SQL, before handing them off to the parser.</p>
</li>
<li><p><strong>Parser</strong>: Processes and validates the syntax of the user query, generating an intermediate parse tree.</p>
</li>
<li><p><strong>Authorization Control</strong>: Verifies the user's permissions to ensure that only authorized actions are performed.</p>
</li>
<li><p><strong>Query Processor</strong>: Converts the user query into a logical execution plan before optimizing it.</p>
</li>
<li><p><strong>Integrity Checker</strong>: Validates that the data meets all the constraints defined on the database while the query executes its statements.</p>
</li>
<li><p><strong>Optimizer</strong>: Analyzes and rewrites the execution plan to choose the most efficient execution strategy.</p>
</li>
<li><p><strong>Executable Code Generation</strong>: Transforms the optimized execution plan into specific calls to the storage engine API.</p>
</li>
<li><p><strong>Transaction Manager</strong>: Coordinates the start, commit, or rollback of transaction operations to ensure atomicity and isolation.</p>
</li>
<li><p><strong>Log (Transaction Record)</strong>: Sequentially records all modifications to ensure durability and recovery support.</p>
</li>
<li><p><strong>Recovery Manager</strong>: Uses the log to restore the database to a consistent state after failures.</p>
</li>
<li><p><strong>Dictionary Manager (Catalog)</strong>: Maintains and queries the metadata <em>(schemas, statistics, permissions)</em> of the database.</p>
</li>
<li><p><strong>Data Manager</strong>: Implements the physical storage data structures and the operations for accessing data.</p>
</li>
<li><p><strong>I/O Processor</strong>: Manages reading and writing of data to disk, that is, persistent memory.</p>
</li>
<li><p><strong>Result Generator</strong>: Formats and sends the result sets (queried data) to the user or the application layer.</p>
</li>
</ul>
<p>Finally, although most databases rely on a DBMS, this is not always the case. For technical or performance reasons, implementing a custom database from scratch may work better for some teams than using a common DBMS-based solution. So a DBMS is not necessary for a database to exist, though it’s present in the vast majority of databases because of its inherent benefits.</p>
<h2 id="heading-chapter-3-data-management-models-and-technologies">Chapter 3: Data Management Models and Technologies</h2>
<p>As you’ve been learning, applications that rely on databases typically involve large amounts of diverse, complex data. Because of this, there’s no single database model that effectively addresses all scenarios. Rather, there are different families, each specializing in specific tasks or sets of tasks.</p>
<p>So here, we’ll explore a range of options that can help you select a database to use in a project, depending on the data and the system's requirements. More specifically, we’ll examine some models or approaches on which a database may be based. But keep in mind that there are many others apart from the ones we’ll discuss here.</p>
<h3 id="heading-types-of-data-according-to-structure">Types of Data According to Structure</h3>
<p>First, the most relevant factor in determining a database's paradigm in a project is the data itself – particularly its complexity. Data complexity is defined by its structure, variability, and internal relationships. This mainly determines how the data is stored and processed.</p>
<p>So, before analyzing the different paradigms or approaches available, you should understand the meaning of <a target="_blank" href="https://www.acceldata.io/blog/data-complexity"><strong>data complexity</strong></a>.</p>
<p>Complexity is a concept that we can informally understand as the degree to which data is "complicated." For instance, a list of integers is different from a graph with integers at each node or a list of numbers encoded in binary, encrypted, or compressed.</p>
<p>Thus, <a target="_blank" href="https://www.aimspress.com/article/doi/10.3934/bdia.2016002?viewType=HTML"><strong>complexity</strong></a> has several dimensions.</p>
<ul>
<li><p><strong>Volume:</strong> Clearly, the more data we have, the harder it will be to manage. It's likely that not all of it will fit on a single machine, resulting in longer processing or query latency times.</p>
</li>
<li><p><strong>Heterogeneity:</strong> This alludes to the vast variety of formats, structures, and origins that data can exhibit within a given information ecosystem. Each of these characteristics constitutes a specific type of <a target="_blank" href="https://www.dremio.com/wiki/heterogeneous-data/">heterogeneity</a>. This concept is more related to the world of data integration than to databases themselves, because it’s the main problem we face when integrating data into a system, regardless of whether it includes a database.</p>
<ul>
<li><strong>Example:</strong> If we are going to build a database of cities and populate it with data from different sources, it’s likely that the city names will be written slightly differently in each source. This is referred to syntactic heterogeneity.</li>
</ul>
</li>
<li><p><strong>Structure:</strong> In our case, this is the key dimension, as it allows us to classify the data into different categories, each of which is associated with a specific database paradigm. Essentially, the structure of the data refers to the extent to which it adheres to a predefined <strong>schema</strong>.</p>
</li>
</ul>
<p>For now, we can understand the <strong>schema</strong> as a formal definition that determines <strong>how</strong> data is organized, as well as the features of this organization depending on the nature of the data and the database. Later, we will focus on the concept of schema in a <strong>structured</strong> (relational) database.</p>
<p>So the complexity of the data depends mainly on two dimensions: the <strong>flexibility</strong> of the schema and the <strong>volume</strong> or <strong>heterogeneity</strong> of the data. The more flexible the schema and the greater the volume or heterogeneity of the data, the more complicated it will be to process it, requiring an appropriate database model.</p>
<p>This means that, regarding the structural dimension of complexity, we can categorize data according to how "rigid" it is.</p>
<p>First, we have <strong>unstructured data</strong>. These are data that do not follow a fixed schema or set of rules for automatic interpretation or labeling without prior processing. They are usually the <strong>most complex</strong> since they are unstructured and lack metadata, or additional information that describes or organizes them. This category includes images, videos, audio, and all kinds of multimedia, such as spatial data.</p>
<p>Next, we have <strong>semi-structured data</strong>. Unlike the unstructured data, this one uses tags as metadata to organize it. This allows the data to be clustered around these tags, which makes it easier to interpret, query, and process. But it can also be self-organized using key-value pairs or internal hierarchies.</p>
<p>Essentially, this data contains <strong>meta-information</strong> that enables its self-organization, though it does not adhere to the strict schema of structured data. For example, we can have data in <strong>XML</strong> or <strong>JSON</strong> format where data is presented as key-value pairs, with a key associated with one or more pieces of data. As such, the key-value pair scheme is not rigid enough to perfectly characterize the structure of the data since it does not explicitly limit the amount of data that can be associated with a tag.</p>
<p>Finally, we have <strong>structured data</strong>. Such data are organized by a strict schema that restricts them to <strong>tabular form</strong>. In other words, the organization is adapted to a schema and follows a series of rules. Each data point is composed of a sequence of values that it takes on a finite number of attributes, where each of these attributes is univalued.</p>
<p>We can think of the schema as the table header that determines the attributes for which each data point takes on values. In this way, a data point is a tuple or row of the table in which it’s stored.</p>
<p>There is one additional restriction: each attribute can only have one value, meaning that an attribute or cell of the table can’t contain more than one value.</p>
<p>Each of these categories leads to one or more database paradigms adapted to their nature. The easiest to deal with are the structured ones, as their rigidity does not allow for sufficient variation for the analytical techniques used on them to be considered "<em>complex</em>." In contrast, the most difficult to deal with are the unstructured ones, due to their variety and high flexibility.</p>
<h4 id="heading-limitations-of-structured-data">Limitations of Structured Data</h4>
<p>To keep things simple, we’ll focus on structured data and the databases supporting it. These databases are built using the <strong>relational model</strong>, which we’ll discuss later.</p>
<p>Since structured data is organized in tables, operating on them is simpler since tables have properties that make them easier to traverse and process. For example, knowing that each cell holds only one value allows us to programmatically traverse all the data in the table by traversing all its rows, regardless of the contents of each cell. This way, we avoid exploring an indeterminate number of values per cell, which would make it much less efficient.</p>
<p>This simplicity also allows tables to be implemented using record- or field-oriented data structures. These provide the necessary efficiency for structuring data within the relational model designed for this type of data. This model is a database "paradigm" that, when used with a query language such as SQL, lets us store and process most structured data, which is why it’s so important.</p>
<p>Keep in mind, though, that its status as a "general" paradigm that addresses almost any problem involving structured data introduces certain limitations:</p>
<h4 id="heading-1-scalability">1. Scalability</h4>
<p>Most relational or structured database implementations use a monolithic architecture. This means the database runs on a single machine and can only be scaled <strong>vertically</strong> by allocating more resources to the machine.</p>
<p>Fortunately, distributed implementations use networks of multiple machines to run the database. This approach allows for <strong>horizontal</strong> scaling by adding more machines to the distributed system, providing greater scalability. Such scalability is critical for products like social networks, ensuring system availability.</p>
<h4 id="heading-2-schema-flexibility">2. Schema Flexibility</h4>
<p>With such a rigid schema, if we need to store unstructured data (like JSON or image data), this requires transformation or an alternative to structured databases, such as <strong>NoSQL</strong> databases. We’ll discuss this more later. These databases allow greater flexibility in data schemas and support heterogeneous data.</p>
<h4 id="heading-3-complex-data-types">3. Complex Data Types</h4>
<p>In addition to having a flexible schema, the type of data we are dealing with may be complex, making querying insufficient. Operations on structured data are usually designed for simple data that will often be queried. But when storing images, graphs, or other complex entities, we may need to perform complex operations on them.</p>
<p>For example, we could need to perform object detection in images or calculate neighborhood and centrality metrics in graphs. This leads to the development of specific database models (which we’ll cover later) that support these operations and the storage of such data, which is usually kept in <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Blob">BLOBs</a>.</p>
<h4 id="heading-4-data-volume-big-data">4. Data Volume (Big Data)</h4>
<p>As previously mentioned, the data volume has an impact on almost every database model, since storing a large amount of data slows down processes. But <strong>Warehousing</strong> and <strong>Data Lake</strong> models can mitigate this effect by leveraging their ability to scale horizontally and accelerate computation to process massive amounts of data faster. This is achieved through techniques like <a target="_blank" href="https://aws.amazon.com/what-is/data-pipeline/?nc1=h_ls">data pipelines</a> or <a target="_blank" href="https://www.ibm.com/think/topics/cluster-computing">cluster computing</a> (similar to <a target="_blank" href="https://aws.amazon.com/what-is/distributed-computing/">distributed computing</a>).</p>
<h4 id="heading-5-real-time-requirements">5. Real-Time Requirements</h4>
<p>Finally, databases are expected to have low <a target="_blank" href="https://aws.amazon.com/what-is/latency/?nc1=h_ls">latency</a> when performing operations, since the speed at which users are served is often determined by the latency of these operations. Also, as the number of users is usually large, the database must support concurrency.</p>
<p>But the persistent storage operations conducted during these processes – plus the mutual exclusion locks that ensure <a target="_blank" href="https://www.geeksforgeeks.org/dbms/concurrency-control-in-dbms/">concurrency</a> (and compliance with ACID principles) – slow down data processing. As a result, <a target="_blank" href="https://aws.amazon.com/nosql/in-memory/">in-memory database</a> implementations are frequently preferred to mitigate this issue. In addition to saving data in persistent storage, these implementations use <strong>RAM memory</strong> as a cache to store some of the data and respond to queries more quickly, achieving a close-to-real-time latency.</p>
<p>So despite being the simplest and most effective at modeling everyday problems, structured databases have certain disadvantages. These have led to the development of alternative database models and approaches. Each of these models attempts to address a specific issue with structured databases, providing support for more complex data and more technically challenging requirements.</p>
<h3 id="heading-big-data">Big Data</h3>
<p>Before examining specific database models, we should consider a problem that affects all of them: the volume of data. When we have a problem with a sufficient amount of data, the term "<a target="_blank" href="https://cloud.google.com/learn/what-is-big-data?hl=en">Big Data</a>" is typically applied. It’s not a model or set of models, but rather a concept referring to massive, complex data sets.</p>
<p>And given how much data is currently produced every day, it’s more and more common to encounter problems where massive volume becomes a limitation.</p>
<p>In a Big Data project, we can divide its lifecycle into several stages.</p>
<ol>
<li><p>First, data is captured from multiple sources and integrated into common formats.</p>
</li>
<li><p>Then, it’s <a target="_blank" href="https://aws.amazon.com/what-is/data-cleansing/?nc1=h_ls">cleaned</a> to ensure correct integration and, when necessary, manually annotated or tagged to feed machine learning models.</p>
</li>
<li><p>The data is then stored in scalable infrastructures or directly in databases, ensuring availability and fast access.</p>
</li>
</ol>
<p>These "<a target="_blank" href="https://en.wikipedia.org/wiki/Data_preprocessing">preprocessing</a>" tasks can account for a significant portion of the work needed before the data is ready for use.</p>
<p>Once processed, we primarily use data to create knowledge models so we can understand the nature of the data. This also lets us generate predictions and informed decisions in professional environments. This process is usually referred to as business intelligence or data-driven decision-making.</p>
<p>These business intelligence processes can also assist with other tasks, such as statistical analysis and visualization. Some of these tasks, including <a target="_blank" href="https://www.ibm.com/think/topics/data-visualization">visualization</a> and statistical analysis, are considered part of the big data ecosystem and are fundamental to data processing. They go along with previous tasks like the management of databases and information systems. So it’s essential to correctly define from the start <strong>what data</strong> is needed for a project, <strong>how</strong> it will be processed, and <strong>what results</strong> are expected.</p>
<h4 id="heading-what-constitutes-big-data">What Constitutes “Big Data”?</h4>
<p>It’s worth noting that, for a project to be considered Big Data, there are no strict conditions for determining whether it belongs to this category. Still, there are a number of factors that contribute to this designation:</p>
<p>The first is volume. As we’ve already discussed, the volume of data refers to the amount of data generated and stored within a given project. The more data that’s generated and stored, the more likely the project is to be categorized as Big Data. Still, there is no specific amount that defines this distinction, as it also depends on other factors, including the availability and complexity of the data.</p>
<p>The next is velocity. This is the rate at which data is generated and must be processed. For example, in a project consisting of a social network or an IoT device network, data may be generated at a very high velocity – that is, a large amount of data per unit of time. This data must be processed as quickly as possible. This means that the faster the data is generated, the more likely it is to be considered part of the Big Data ecosystem.</p>
<p>The last main factor is variety, also called data heterogeneity. This means the more heterogeneous the data, the more difficult it is to process. This requires greater computing power, which makes the project more likely to be considered Big Data.</p>
<p>For instance, integrating data from sources that use the same formats is easier than integrating data from those that use different ones.</p>
<p>Heterogeneity is affected not only by the formats, but also by how they are encoded, transmitted, and so on. We also need to consider the level of data structuring because unstructured or unlabeled data likely requires machine learning techniques (such as <a target="_blank" href="https://www.freecodecamp.org/news/8-clustering-algorithms-in-machine-learning-that-all-data-scientists-should-know/">clustering</a>) to extract information from it.</p>
<p>These are the main factors, although more have been added over time thanks to technological advances in these processes. Among them are:</p>
<ul>
<li><p><strong>Veracity</strong>: Degree of reliability of the information received in terms of data quality and accuracy, in order to avoid decisions based on incorrect or biased information.</p>
</li>
<li><p><strong>Viability:</strong> The degree to which the data can be effectively used in the project, as sometimes their volume or other factors make their processing technically unfeasible.</p>
</li>
<li><p><strong>Visualization:</strong> It's the ease with which data can be transformed into understandable dashboards for users, allowing them to explore it intuitively.</p>
</li>
<li><p><strong>Value:</strong> The expected value to be obtained from processing the data. Generally, it's economic value, although it doesn't need to be economic – it mainly depends on the application domain.</p>
</li>
<li><p><strong>Viscosity:</strong> This is the significance that data have in decision-making. Not the value added by their processing, but the relevance they have when making a decision.</p>
</li>
</ul>
<p>In summary, although volume is one of the key factors determining whether a problem or project is considered Big Data, it’s not the only one. The speed at which data is generated and the heterogeneity of the data require a large amount of computation to process it, which is the primary issue that led to the concept of Big Data.</p>
<h3 id="heading-nosql-databases">NoSQL Databases</h3>
<p>The first model or database approach we’ll examine is <a target="_blank" href="https://cloud.google.com/discover/what-is-nosql?hl=en"><strong>NoSQL</strong></a>. Its name indicates that these databases aren’t only structured, but also that the data can vary in structure.</p>
<p>The main characteristic of this database approach is its <strong>flexibility</strong> in storing data – it doesn’t force data to adhere to a fixed schema, such as a tabular one. They also focus on offering easy <strong>horizontal scalability</strong>, which allows the computational capacity of the database to be expanded by increasing the number of machines. This makes them efficient at processing complex, large-volume data and thus supporting Big Data problems.</p>
<p>To understand what they entail in practice, we could consider a use case involving a database for a bicycle rental system, that lets users rent bicycles through a subscription.</p>
<p>To implement this system, we can choose from a wide variety of databases or information systems. For example, in a <strong>relational database</strong>, the information is organized in tables, whereas <strong>NoSQL</strong> databases use different types of structures to organize the data. Each structure yields a specific type of NoSQL database.</p>
<p>Without delving into the specifics of the use case, we can see that using a relational database for such a project may pose challenges in the following areas:</p>
<ul>
<li><p><strong>Volume:</strong> If the system is deployed nationally or on a continental scale, a large number of users will perform transactions in our system, either by using or returning bicycles or by contracting or canceling their subscription to the service. Above all, scaling a relational database has the greatest impact on the system. To manage such a large number of users, the system requires powerful computing capacity to match to needs. This means that the database must be able to scale horizontally to reach optimal capacity. In relational databases, vertical scaling is usually applied, but it becomes costly to add more computing capabilities beyond a certain threshold.</p>
</li>
<li><p><strong>Velocity:</strong> The system must respond quickly to user requests, such as displaying available bikes within a certain area or managing subscriptions. If the system uses a relational database, ensuring concurrency is computationally expensive, which causes high latency when many users query or modify the same information simultaneously.</p>
</li>
<li><p><strong>Rigid schema:</strong> In a relational database, the schema does not frequently change. So if our system requires regular updates (like updates to bike models, the addition of new bike sensors, or significant modifications to the subscription service, especially the addition of functionalities or new features), these changes will require updating the database schema by adding or removing columns. This process is costly and complicated once the system is in production and its tables contain a large amount of data.</p>
</li>
<li><p><strong>Temporal Analysis:</strong> Since structured databases are composed of tables, as we will learn later, if we need to perform a time series analysis or analyze data spanning a long period of time with a large number of records throughout that period, the database's response latency will be high. For example, consider calculating metrics on bike usage over the last 10 years, during which time there may have been a massive number of transactions between users and bicycles. These types of queries are often called analytical queries.</p>
</li>
</ul>
<p>NoSQL databases offer different solutions to these problems, depending on how the data needs to be structured. So for each of these ways of organizing and storing data, there is a certain type of NoSQL database with a series of advantages and disadvantages depending on the nature of the project and the data involved. Let’s look at them now.</p>
<h4 id="heading-key-value-model">Key-Value model</h4>
<p>The simplest option is to store all the data in a dictionary of <a target="_blank" href="https://www.mongodb.com/resources/basics/databases/key-value-database"><strong>key-value pairs</strong></a>, where each key is a unique identifier that acts as a tag linked to a single value. The type of content of each value depends on how we need to organize the data.</p>
<p>Here, we use the term "<a target="_blank" href="https://en.wikibooks.org/wiki/A-level_Computing/AQA/Paper_1/Fundamentals_of_data_structures/Dictionaries">dictionary</a>" to refer to the data structure used in languages such as Python and Java, as well as in languages where the dictionary structure is the only method of representing information, such as in JSON. In our use case, if we want to store user information, each user could be represented as a dictionary with the following <a target="_blank" href="https://aws.amazon.com/nosql/key-value/"><strong>key-value</strong></a> pairs:</p>
<pre><code class="lang-json">{
  <span class="hljs-attr">"id"</span>: <span class="hljs-number">27</span>,
  <span class="hljs-attr">"name"</span>: <span class="hljs-string">"Juan"</span>,
  <span class="hljs-attr">"email"</span>: <span class="hljs-string">"juan@juan.com"</span>,
  <span class="hljs-attr">"birth"</span>: <span class="hljs-string">"1984-01-05"</span>
}
</code></pre>
<p>As you can see, keys serve as names that identify the value we are storing in a given pair. In this case, the key is the user's name, although we can also save binary content or a Boolean value as the key.</p>
<p>Among this model's characteristics are:</p>
<ul>
<li><p>its simplicity, which enables humans to easily understand it</p>
</li>
<li><p>its low latency, which benefits from data structures such as hash tables with very low access times, and</p>
</li>
<li><p>its ease of distribution on several machines, since a dictionary can be seamlessly partitioned by its keys. In practice, <a target="_blank" href="https://redis.io/"><strong>Redis</strong></a> is the most common DBMS used for this kind of database.</p>
</li>
</ul>
<h4 id="heading-document-model">Document model</h4>
<p>In this model, the information management unit is not a key-value pair, but rather a set of them, known as a "document.</p>
<p>The main difference from the previous <strong>key-value</strong> model is that the values are no longer "opaque." Here, a document holds its information in a nested, hierarchical structure. This means that a value might be a dictionary containing key-value pairs, some of which can also be dictionaries. Thus, a hierarchy is established within the stored information, rather than allowing the values to be of any kind as in the key-value model.</p>
<p>Some characteristics of the document model are its <strong>flexible schema</strong> and the <strong>hierarchical storage</strong> of heterogeneous data. For example, in our use case, we can store bike information as follows:</p>
<pre><code class="lang-json">bike1 = {
  <span class="hljs-attr">"id"</span>: <span class="hljs-number">1</span>,
  <span class="hljs-attr">"model"</span>: <span class="hljs-string">"model1"</span>,
  <span class="hljs-attr">"status"</span>: <span class="hljs-string">"available"</span>
}

bike2 = {
  <span class="hljs-attr">"id"</span>: <span class="hljs-number">2</span>,
  <span class="hljs-attr">"model"</span>: <span class="hljs-string">"model2"</span>,
  <span class="hljs-attr">"status"</span>: <span class="hljs-string">"in_use"</span>,
  <span class="hljs-attr">"sensors"</span>: {
    <span class="hljs-attr">"cadence"</span>: <span class="hljs-number">85</span>,
    <span class="hljs-attr">"speed"</span>: <span class="hljs-number">24.5</span>
  }
}

bike3 = {
  <span class="hljs-attr">"id"</span>: <span class="hljs-number">3</span>,
  <span class="hljs-attr">"model"</span>: <span class="hljs-string">"model3"</span>,
  <span class="hljs-attr">"status"</span>: <span class="hljs-string">"maintenance"</span>,
  <span class="hljs-attr">"sensors"</span>: {
    <span class="hljs-attr">"gps"</span>: {
      <span class="hljs-attr">"latitude"</span>: <span class="hljs-number">40.4168</span>,
      <span class="hljs-attr">"longitude"</span>: <span class="hljs-number">-3.7038</span>
    },
    <span class="hljs-attr">"camera"</span>: <span class="hljs-string">"front_hd"</span>
  },
  <span class="hljs-attr">"acquisitionDate"</span>: <span class="hljs-string">"2024-11-15"</span>
}
</code></pre>
<p>Here, you can see that all the dictionaries represent bikes. But some contain more fields than others depending on the information that the specific bike model yields. This prevents the need for several tables to be created for each model or type of bike. You can also see that some fields have a dictionary as a value, which hierarchizes the data. Also, not all fields need to be structured equally since the model allows for some <strong>heterogeneity</strong> in this regard.</p>
<p>Finally, it’s important to emphasize that, in this model, the documents are self-descriptive, as the names of the keys or tags identify the stored information. <a target="_blank" href="https://www.mongodb.com/"><strong>MongoDB</strong></a> is one of the main DBMSs for implementing this model.</p>
<h4 id="heading-column-oriented-model">Column-oriented model</h4>
<p>This model is similar to the <strong>structured</strong> model (the one used in relational databases) where information is stored in tables – but instead of each data point being kept in a row, it’s stored in a <a target="_blank" href="https://www.geeksforgeeks.org/dbms/columnar-data-model-of-nosql/"><strong>column</strong></a>. For example, in our use case, we could have:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Attribute</strong></td><td>bike1</td><td>bike2</td><td>bike3</td></tr>
</thead>
<tbody>
<tr>
<td><strong>model</strong></td><td>model1</td><td>model2</td><td>model3</td></tr>
<tr>
<td><strong>status</strong></td><td>available</td><td>in_use</td><td>maintenance</td></tr>
<tr>
<td><strong>sensor_cadence</strong></td><td>–</td><td>85</td><td>–</td></tr>
<tr>
<td><strong>sensor_speed</strong></td><td>–</td><td>24.5</td><td>–</td></tr>
</tbody>
</table>
</div><p>In this type of database, the points are still rows in a table. But the items that the management system considers to compose the table aren’t the rows, but the columns.</p>
<p>In a relational database, a set of rows composes a table, where each row is a data point holding values taken for certain attributes, which are the columns. Similarly, in the <a target="_blank" href="https://en.wikipedia.org/wiki/Data_orientation"><strong>column-oriented model</strong></a>, the management system treats a column as a "data point" on which operations are performed.</p>
<p>As illustrated above, a table from the relational model is transposed so that each column becomes a bicycle instead of an attribute. In the column-oriented model, each data point is a column, allowing analytical queries to be executed quickly since all the values of a column are considered a single "data point," which significantly speeds up <strong>aggregation</strong> operations.</p>
<p>Furthermore, better data compression is generally achieved since all the data in a column is of the same type. Simple horizontal scalability is also possible through techniques such as column sharding. One of the most popular DBMS for this model is <a target="_blank" href="https://hadoop.apache.org/"><strong>Hadoop</strong></a>.</p>
<h4 id="heading-graph-model">Graph model</h4>
<p>Alternatively, there is the <a target="_blank" href="https://aws.amazon.com/nosql/graph/"><strong>graph model</strong></a>, which relies on <a target="_blank" href="https://www.w3schools.com/dsa/dsa_theory_graphs.php"><strong>graphs</strong></a> as fundamental data structures for storing information and relationships between data.</p>
<p>In our use case, for instance, each node can represent entities ranging from people to bicycles, connected by edges representing relationships between them, such as subscriptions or rentals. Both nodes and edges can contain attributes, allowing us to further organize the information.</p>
<p>This model is characterized by its support for analysis and big data projects since problems that tend to be modeled with graphs often involve large volumes of information, such as social networks. Also, graphs as data structures allow for the modeling of complex information and relationships. <a target="_blank" href="https://neo4j.com/"><strong>Neo4j</strong></a> is a popular option here, but there’s a variety of other DBMSs oriented toward specific uses within this model.</p>
<h3 id="heading-data-warehousing">Data Warehousing</h3>
<p>Apart from the different options offered by the NoSQL model, you may have other needs that require different types of models. NoSQL is currently focused primarily on efficient data storage and querying. It’s especially useful in projects where data generation is the bottleneck – that is, a system that specializes in storing data is needed.</p>
<p>Conversely, other projects, especially those related to organizations, require a system that not only stores data efficiently but also manages the difficulty of extracting strategic information, as data lacks value on its own. The <a target="_blank" href="https://www.geeksforgeeks.org/dbms/data-warehousing/"><strong>Warehousing model</strong></a> offers support for the centralization, organization, and subsequent transformation of data into knowledge that guides decision-making.</p>
<h4 id="heading-what-is-a-data-warehouse">What is a Data Warehouse?</h4>
<p>A <a target="_blank" href="https://cloud.google.com/learn/what-is-a-data-warehouse?hl=en"><strong>Data Warehouse</strong></a> is essentially a specialized database for centrally storing large volumes of data from multiple sources. Besides storing all the data in "a single system" in a centralized way, its main purpose involves optimizing analytical queries on the data and generating dashboards or reports from the analysis itself. This is all aimed at supporting the efficient analysis and storage of the data.</p>
<p>By "<a target="_blank" href="https://docs.vertica.com/23.4.x/en/data-analysis/sql-analytics/analytic-query-examples/">analytical queries,</a>" I mean queries that require information over a certain period of time (or a different dimension) to calculate a metric on the data, such as the average magnitude over a 10-year period.</p>
<p>Returning to the previous example of the bicycle rental system, the Warehousing model provides advantages in terms of efficiency in storing users' bicycles and transactions, such as rentals or subscriptions. It also supports complex analytical queries on the data that contribute to strategic decision-making regarding the system. Such queries aim to predict demand and revenue, detect which parking areas are used more or less frequently, and so on.</p>
<h4 id="heading-main-features-of-data-warehouses">Main Features of Data Warehouses</h4>
<p>Now let’s look at some of the main features of a Data Warehouse so you undertstand how they work.</p>
<h4 id="heading-theyre-integrated">They’re Integrated</h4>
<p>A data warehouse is typically a database that stores information from various sources. It integrates this information using transformations and processes that address the heterogeneity of the data, adapting it to the warehouse's common schema.</p>
<p>In our example, data can stem from various systems, including GPS positioning of bicycles, parking occupancy sensors, payment and subscription systems, and mobile applications. The warehouse then integrates all of this data, standardizing it into a common format to make its collective analysis easier. Note that these <strong>sources</strong> can vary greatly in nature, with some being structured and others not.</p>
<h4 id="heading-they-have-a-historical-dimension">They Have a Historical Dimension</h4>
<p>Over time, the Warehouse accumulates information from different sources to enable analytical queries. In our example, this would correspond to analyzing the data itself, such as examining user and bicycle behavior and usage, analyzing demand or revenue, among other possibilities.</p>
<h4 id="heading-theyre-optimization-for-reading">They’re Optimization for Reading</h4>
<p>Given the objectives we want to achieve with a warehouse, it’s optimized primarily for queries that only access data without modifying it, which is precisely what analytical queries require.</p>
<p>In our example, it would not be very efficient to implement the entire information system in a warehouse because of the need to optimize write operations. One possible solution would be to use the warehouse only to store data reserved for analysis, while providing the actual service to users with a more suitable system.</p>
<p>In other words, even if we use a different database to implement the bike rental service, we can also have a warehouse into which we periodically insert information that needs to be analyzed.</p>
<h4 id="heading-different-data-warehousing-schemas">Different Data Warehousing Schemas</h4>
<p>In addition to these characteristics, a data warehouse is primarily a database consisting of tables. So, if the data is highly complex or has too many dimensions, we can organize it into different data models.</p>
<h4 id="heading-1-star-schemahttpsenwikipediaorgwikistarschema">1. <a target="_blank" href="https://en.wikipedia.org/wiki/Star_schema">Star Schema</a></h4>
<p>Here, the data or measurements are mainly stored in a central table called the fact table, which is related to other tables representing possible dimensions for analyzing the data in the fact table. The main feature of this model is that the dimensional tables aren’t usually subdivided into more specific dimensions, as the goal here is to find a simple way to store data to speed up analytical queries as much as possible.</p>
<p>In our example, if you only need to build dashboards for usage, billing, or similar purposes, prioritizing query speed, you could opt for a star schema with a large rentals table containing fields like user, bike, origin/destination station, date, and cost, and surrounding tables for each of those entities that can be considered "<em>dimensions</em>" when analyzing that data.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/b/bb/Star-schema.png" alt="Show an example of a Star schema, with a central fact table connected to several dimension tables around it. From https://en.wikipedia.org/wiki/Star_schema" class="image--center mx-auto" width="998" height="626" loading="lazy"></p>
<h4 id="heading-2-snowflake-schemahttpsenwikipediaorgwikisnowflakeschema">2. <a target="_blank" href="https://en.wikipedia.org/wiki/Snowflake_schema">Snowflake schema</a></h4>
<p>Unlike the star data model, with a snowflake schema each surrounding table can be further subdivided into specific sub-dimensions, meaning smaller tables related to each other. This often saves space and improves data quality by reducing redundancy, as there are specific tables storing specific information and relating it to the rest of the tables, avoiding the duplication of information in too many tables. This streamlines the management of larger, more complex data sets.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/b/b2/Snowflake-schema.png" alt="An example of a Snowflake schema, with a central fact table connected to several dimension tables subdivided into more dimensions around it. https://en.wikipedia.org/wiki/Snowflake_schema" class="image--center mx-auto" width="1459" height="881" loading="lazy"></p>
<h4 id="heading-etl-extraction-transformation-and-load">ETL (Extraction, Transformation, and Load)</h4>
<p>As you’ve now learned, a Data Warehouse is populated with data from multiple sources, all potentially different in nature. So Data Warehouses need to have a component responsible for extracting data from the sources, processing it, and inserting it into the data warehouse. This component is the <a target="_blank" href="https://cloud.google.com/learn/what-is-etl?hl=en"><strong>ETL</strong></a>, which is a specific software piece for each data source that handles:</p>
<ul>
<li><p><strong>Extraction:</strong> Obtains data from the source in the provided format.</p>
</li>
<li><p><strong>Transformation:</strong> It applies a series of transformations to clean them, eliminate heterogeneity, and adapt them to the schema defined in our Warehouse. The complexity and detail of these transformations mainly depend on the problem being addressed, even leading to the derivation or prediction of new data from existing records.</p>
</li>
<li><p><strong>Load:</strong> It inserts them into the Warehouse.</p>
</li>
</ul>
<p>ETL processes are typically run periodically to populate the Data Warehouse or update the data within it.</p>
<p><img src="https://upload.wikimedia.org/wikipedia/commons/thumb/c/c7/Extract%2C_Transform%2C_Load_Data_Flow_Diagram.svg/1280px-Extract%2C_Transform%2C_Load_Data_Flow_Diagram.svg.png" alt="Diagram of an ETL process. It extracts data from sources, transforms it, and loads it into an information system. From https://en.wikipedia.org/wiki/Extract,_transform,_load" class="image--center mx-auto" width="1280" height="967" loading="lazy"></p>
<h4 id="heading-olap">OLAP</h4>
<p>As you’ve already seen, Data Warehousing is designed to support analytical queries, commonly known as <a target="_blank" href="https://aws.amazon.com/what-is/olap/"><strong>OLAP (Online Analytical Processing)</strong></a>. Unlike <a target="_blank" href="https://www.oracle.com/database/what-is-oltp/"><strong>OLTP (Online Transactional Processing)</strong></a>, which focuses on reading or modifying records individually, OLAP allows for analyzing data across various dimensions to discover trends or patterns that support strategic decision-making.</p>
<p>To understand this, it's very common to think about queries on the time dimension, which is the easiest to see, such as calculating an average over data from a time period or any similar metric.</p>
<p>More specifically, in an <a target="_blank" href="https://www.geeksforgeeks.org/dbms/olap-operations-in-dbms/"><strong>OLAP environment</strong></a>, data is organized into multidimensional <strong>cubes</strong>, where each dimension represents a perspective of analysis like time, product, region, and so on, and the data or <strong>measures</strong> are the quantitative values that are <strong>aggregated</strong> according to the dimensions we are interested in.</p>
<p>Some basic navigation and aggregation <a target="_blank" href="https://www.ibm.com/think/topics/olap"><strong>operations</strong></a> are defined on these cubes:</p>
<ul>
<li><p><strong>Drill-Down:</strong> It involves moving from a high level of aggregation to a more detailed one. For example, after reviewing the total quarterly bike rentals, we apply drill-down to see those that occurred by month, and from there by day or even by parking spot, allowing us to quickly detect usage variations in specific periods.</p>
</li>
<li><p><strong>Roll-Up:</strong> This is the opposite operation to drill-down: it groups data into higher levels of detail. Starting from daily rentals, with a roll-up, we can obtain monthly rentals, by region, or the annual total, helping summarize large volumes of data and provide an overall view of the modeled domain.</p>
</li>
<li><p><strong>Slice:</strong> Here, a subset of data is selected by setting a value in one dimension. For example, a "slice" in the bike rental cube by setting the dimension <strong>"region = Spain"</strong> will show all bike rentals that have occurred in Spain, while keeping other dimensions like time or other services (service subscription) fixed.</p>
</li>
<li><p><strong>Dice:</strong> Similar to slicing, a <strong>"filter"</strong> is applied to the cube across multiple dimensions simultaneously. For example, querying bike rentals in a specific geographic region and during a certain time period. The main difference is that a range is defined in several dimensions at once, creating a sub-cube with more specific results.</p>
</li>
<li><p><a target="_blank" href="https://www.numberanalytics.com/blog/mastering-data-pivoting-data-warehousing"><strong>Pivot</strong></a><strong>:</strong> This involves rearranging the dimensions of the cube to change the analysis perspective without altering the data. For example, swapping rows and columns in a report to view regions in columns and periods in rows, making it easier to compare different dimensions and discover correlations between them.</p>
</li>
</ul>
<h3 id="heading-data-lakes">Data Lakes</h3>
<p>In addition to the Warehousing model, we have <a target="_blank" href="https://cloud.google.com/learn/what-is-a-data-lake?hl=en"><strong>Data Lakes</strong></a>, which are like Warehouses where data is not stored following a common schema but is kept as it stems from its respective sources. That is, to populate a Warehouse with data, ETL components are needed to transform and adapt it to a <strong>schema</strong>. But with a data lake, such components do not exist because there is no schema that the data must follow – instead, it’s simply stored in its original format and structure.</p>
<p>The main reason for this is that a Data Lake aims to analyze the data, while a Warehouse aims to integrate the data through transformations to turn it into knowledge that supports high-level <a target="_blank" href="https://www.revealbi.io/blog/data-warehousing"><strong>business decision analysis</strong></a>.</p>
<p>Normally, data is stored in its raw form in a data lake without any processing, although it can be organized according to the project's needs. This implies that the associated costs are generally lower than those of a Warehouse, as it saves all the computation resources related to its transformation, which can sometimes be complex and computationally expensive.</p>
<p>Since Data Lakes focus on <strong>storing</strong> data rather than <strong>integrating</strong> it, they are suitable for <strong>machine learning tasks</strong> and <a target="_blank" href="https://www.ibm.com/think/topics/exploratory-data-analysis"><strong>exploratory analysis</strong></a>. It's easy to apply algorithms to find patterns in raw data. But don't confuse non-integrated data with unlabeled data. <a target="_blank" href="https://www.freecodecamp.org/news/supervised-vs-unsupervised-learning/"><strong>Labeled data</strong></a> can be stored in a Data Lake and used to train supervised machine learning models. It all depends on the project's needs and the level of abstraction you want to work with.</p>
<h3 id="heading-semantic-web">Semantic Web</h3>
<p>In addition to the previous database models, there are other types of technologies and tools that can organize data and its semantics. One of these technologies is the <a target="_blank" href="https://en.wikipedia.org/wiki/Semantic_Web"><strong>Semantic Web</strong></a>, which arises from the need to provide meaning to the terms used on the traditional web.</p>
<p>For example, in an HTML document, the word "user1" might appear, which by itself is just data without any meaning. So to integrate semantics, the Semantic Web is used as a "layer" of software that associates meaning to the terms that appear on the web.</p>
<p>While a simple HTML document serves to structure a series of data at the <strong>layout</strong> level, the Semantic Web provides meaning, usually through tags or annotations, so they can be interpreted by both humans and machines. In this way, the data "user1" can be associated with a tag like "name”, indicating that the data is a username.</p>
<p>This technology is based on a series of components:</p>
<ul>
<li><p><strong>RDF (Resource Description Framework):</strong> A <a target="_blank" href="https://en.wikipedia.org/wiki/Resource_Description_Framework"><strong>standard</strong></a> where information is represented through <a target="_blank" href="https://stackoverflow.com/questions/273218/whats-a-rdf-triple"><strong>Subject – Predicate – Object</strong></a> triples, where the subject is usually a resource or entity within the domain, the predicate is an attribute or relationship that the entity has with a value, which is the object of the triple. This way of representing information is easily understandable by people and easily processed by machines, being independent of the language used to manage the triples (such as <strong>XML</strong> or <strong>Turtle</strong>).</p>
<pre><code class="lang-xml">  <span class="hljs-tag">&lt;<span class="hljs-name">http:</span>//<span class="hljs-attr">example.org</span>/<span class="hljs-attr">users</span>/<span class="hljs-attr">user1</span>&gt;</span> domain:name "Juan"
</code></pre>
</li>
<li><p><strong>Vocabularies:</strong> A set of terms used to describe data in a specific domain. We can see this as a language or dictionary of concepts with their associated meanings, all belonging to a common domain. More specifically, it can have meanings associated with classes (sets of entities), properties of those entities, or relationships between them.</p>
<ul>
<li><strong>Example:</strong> <a target="_blank" href="https://en.wikipedia.org/wiki/Dublin_Core">https://en.wikipedia.org/wiki/Dublin_Core</a></li>
</ul>
</li>
<li><p><strong>Ontologies:</strong> A formal conceptualization of a domain, where the meanings of the entities within it are defined, along with their properties, relationships with other entities, hierarchies they form among themselves, and their constraints. In summary, they provide richer semantics than vocabularies due to the complexity with which they can model semantics.</p>
<ul>
<li><strong>Example:</strong> <a target="_blank" href="http://musicontology.com/docs/getting-started.html">http://musicontology.com/docs/getting-started.html</a></li>
</ul>
</li>
</ul>
<p>In relation to the web, there are multiple ways we can store our data, whether on our own <a target="_blank" href="https://www.hpe.com/emea_europe/en/what-is/on-premises-vs-cloud.html">infrastructure</a> or someone else's. On one hand, we can choose to have a complete infrastructure of our own where all data is handled locally <strong>(on-premise)</strong>, which offers advantages like having full control over it or faster access. But this also has drawbacks such as high costs since we have to maintain the entire infrastructure ourselves, ensure good scalability, and minimize the risk of failures that could reduce service availability.</p>
<p>On the other hand, you can choose to use someone else's infrastructure, usually by renting it. Here, the data is in the <strong>cloud</strong>, which provides greater scalability, reduced costs since you only pay for the infrastructure you use, broad geographic access with services like GCP or AWS, and backup services that minimize the risk of data loss, which would be potentially very expensive to achieve using local infrastructure.</p>
<p>Still, this approach also has drawbacks, such as the dependency on an internet connection to use the infrastructure as a service, or security and privacy issues since the data is in a place we don't know well.</p>
<p>Finally, keep in mind that these two types of solutions aren’t mutually exclusive. You can use them simultaneously in <a target="_blank" href="https://www.shakudo.io/blog/cloud-vs-on-premise-vs-hybrid">hybrid solutions</a> where the most sensitive or valuable data is kept locally and the rest on external infrastructure, although this strongly depends on the project's requirements.</p>
<h2 id="heading-chapter-4-database-design">Chapter 4: Database Design</h2>
<p>Now that you’ve learned about some existing database models and the technologies that support them, it's important to understand what database design means.</p>
<p>In short, <a target="_blank" href="https://guides.visual-paradigm.com/navigating-the-three-levels-of-database-design-conceptual-logical-and-physical/"><strong>database design</strong></a> refers to a database’s creation. When you have a project involving data, the first order of business is to consider is whether you actually need a database. This typically depends on factors like requirements provided by a client.</p>
<p>If you need a database, its <a target="_blank" href="https://www.geeksforgeeks.org/dbms/database-design-in-dbms/">design</a> typically follows a series of stages. These stages start with the client's requirements, which determine what needs to be stored and how it needs to be stored. Then, the schema or structure that the data should follow once storage is planned. This allows you to further explore how to store and process the data computationally at a low level to optimize the most critical operations.</p>
<p>For example, in projects like product sales platforms, it may be more important to optimize operations related to product searches, while in others such as social networks, optimizing the writing of new posts may be more significant.</p>
<p>In addition to deciding the <strong>structure</strong> of the data, user requirements also help determine which data needs to be stored, as it's not always necessary to keep all available data in a database. Generally, only the data that might be retrieved or used in some operation is stored, although this strongly depends on the project's requirements and nature.</p>
<h3 id="heading-database-design-levels">Database Design Levels</h3>
<p>When you’re developing a data project and working on designing the database, you can divide it into a series of stages or <strong>design levels</strong>. These are related to the level of abstraction with which you can view the implementation of the database. Think of them as steps to follow to achieve a functional database that meets user requirements which are also considered part of the database design.</p>
<p>Apart from these design levels, there is a distinction based on the area of the development they are oriented towards, usually distinguishing three areas in which the different design levels are classified.</p>
<ul>
<li><p>On one hand, there is the <strong>analysis</strong> of the client's needs and requirements, which determines what our information system must do.</p>
</li>
<li><p>Then we have the <strong>design</strong> of the database itself, which provides a description of the solution, its practical implementation, and the software/hardware components that form it.</p>
</li>
<li><p>Finally, we have the <strong>technology</strong> used for this implementation, where the tools, programs, and specific modules involved in the development are decided.</p>
</li>
</ul>
<p>Now let’s look at the different design levels.</p>
<h4 id="heading-1-analysis-functional-and-data-requirements">1. Analysis (Functional and Data Requirements)</h4>
<p>This level is considered part of database design due to its influence on the other stages or levels. Here, information about the domain is first gathered, which can stem from clients, users, or any stakeholder with knowledge about the domain. The main goal is to obtain as much information as possible to then extract <a target="_blank" href="https://qat.com/guide-writing-data-requirements/"><strong>user requirements</strong></a> from it. These are a series of axioms that determine what the system must do to function according to the client's needs.</p>
<p>These requirements can be of many types, all <a target="_blank" href="https://www.geeksforgeeks.org/software-engineering/software-engineering-classification-of-software-requirements/">studied in depth</a> in the field of software engineering. A significant feature about them is that they determine <strong>what</strong> the system must do, not <strong>how</strong> it should do it, although in certain systems there are requirements for correctness or security that might restrict how the system should perform certain actions.</p>
<p>For example, if we design a database for a <a target="_blank" href="https://en.wikipedia.org/wiki/Safety-critical_system">critical system</a> like a nuclear power plant, it’s very likely that some of those requirements will require the system to respond to certain critical queries within a short time frame for safety reasons.</p>
<h4 id="heading-2-conceptual-design-high-level-erduml">2. Conceptual Design (High-Level ERD/UML)</h4>
<p>Once the requirements that the system or database must meet are clear, the <a target="_blank" href="https://www.tutorialspoint.com/conceptual-database-design">conceptual design</a> is responsible for describing how the data will be organized within the database. This is always done according to the database model you’ve selected for the project, as using NoSQL is different from using a structured database.</p>
<p>To correctly understand this level, let’s consider a case where the database being used is relational/structured. At this level, the data is first described, along with their possible associated constraints, such as data types, attribute domains, and so on. Then, software engineering tools like an <a target="_blank" href="https://www.lucidchart.com/pages/er-diagrams">entity-relationship diagram</a> are used to describe the tables that comprise the database and their relationships. This helps us formalize the structure in which the data will be organized once the system is in production.</p>
<p>It’s important to remember that regardless of the tool used for this process (whether a diagram or any other representation method), the organization depicted in the diagram must later be translated into a software implementation, which heavily depends on the DBMS. Designing a <strong>structured</strong> database differs from designing a <strong>graph-oriented</strong> database, so you’ll need to select an appropriate tool at this level to represent the data organization.</p>
<p>So the main focus at this level, beyond understanding the requirements, is to organize how the information is stored according to the operations the system will support. You’ll also need to properly document the descriptions provided, whether with diagrams or other tools, so they are understandable later and can be implemented on a specific DBMS.</p>
<h4 id="heading-3-logical-design-relational-schema">3. Logical Design (Relational Schema)</h4>
<p>Assuming the database is <strong>structured</strong>, at this level, you’ll use the diagram you created in the previous level to implement the database schema on a DBMS. This means you define the tables that the database will have on the DBMS.</p>
<p>If you didn’t use a diagram in the previous level or the database is not structured, you’ll follow the same process – although instead of tables, you’ll use the appropriate structures, such as graphs. Ultimately, here the <strong>entity-relationship</strong> diagram is translated into a <strong>relational</strong> schema, as we will see later, which is responsible for representing the tables that exist in the database at the DBMS layer.</p>
<p>When dealing with tables (or the corresponding structure according to the database model you’re using), it’s easy to understand how the database is organizing the information. But this is only the <strong>high-level</strong> view, in that DBMSs show us how data is organized, since eventually everything has to be converted into <strong>low-level</strong> data structures and algorithms on files that work with information encoded in binary. In other words, although we see tables, internally the DBMS operates with other types of computational tools at a lower level, closer to the hardware, which do not necessarily have to resemble tables, graphs, key-value pairs, and so on.</p>
<p>This offers an advantage: when managing the database, you can do so by focusing on the tables it contains, without needing to worry about how the data is actually stored in memory (or how the data structures and algorithms used to implement the database operations are working).</p>
<p>In other words, the database, more specifically the DBMS, automatically translates <a target="_blank" href="https://youtu.be/KQKHzsypxh4?si=GQOSlhXHAbXu4NfK">table-level</a> management into the lowest level management, closer to the hardware, which is called <a target="_blank" href="https://www.geeksforgeeks.org/dbms/physical-and-logical-data-independence/">logical-physical independence</a>. This allows us to manipulate the database by working directly with the tables, not with the content at the hardware level, which would complicate things.</p>
<p>Finally, at this level, you’ll often perform <a target="_blank" href="https://enter77.ius.edu/cjkimmer/schema-refinement/">schema refinement</a>. This refers to restructuring the schema with tables to make certain operations more efficient, or to improve certain aspects of the implementation according to the requirements. We do this because, when translating from the previous level to the <a target="_blank" href="https://youtu.be/Ex6wszg2XZ8?si=54NuziZRbPPyDe4B">logical</a> one, you can modify certain design patterns to better use the tools provided by the DBMS, whether table-oriented or not.</p>
<h4 id="heading-4-physical-design-logical-indexes-clustering-partitions">4. Physical Design (Logical Indexes, Clustering, Partitions)</h4>
<p>At this level, the DBMS automatically implements the schema we previously defined at the level closest to the <a target="_blank" href="https://www.ibm.com/docs/en/db2-for-zos/12.0.0?topic=relationships-physical-database-design">hardware</a>. It translates the set of tables and associations we defined into specific <a target="_blank" href="https://docs.oracle.com/cd/A84870_01/doc/server.816/a76994/physical.htm">data structures</a> like B-trees, indexes, and algorithms that support their operations. In essence, this level is the computational implementation of the DBMS, which manages disk memory or calls the operating system, among other details.</p>
<p>This implementation of our schema by the DBMS is automatic. We simply need to provide a definition based on the relational schema we created earlier, including the tables, associations between them, and the data we want to insert or delete.</p>
<p>With this, the DBMS translates these "relational" operations into low-level operations like assembly instructions. This helps us maintain <a target="_blank" href="https://youtu.be/IwOp4R5PzU0?si=4ovVsvfZjdnokYbe">logical-physical independence</a>, as the DBMS implementation can be modified at any time without affecting our <strong>relational schema</strong> or its functionality. This lets us optimize the DBMS code without needing to rewrite all the "relational" programs that define the databases.</p>
<h4 id="heading-5-storage-level-block-formats-disk-structures-and-access">5. Storage Level (Block Formats, Disk Structures, and Access)</h4>
<p>You can think of this level as a subset of the previous one, as it’s responsible for <a target="_blank" href="https://www.geeksforgeeks.org/system-design/file-and-database-storage-systems-in-system-design/">storing</a> data in secondary memory according to the relational schema managed by the DBMS. It performs the necessary requests to the operating system to allocate memory and usually manages information on the disk at the byte level.</p>
<p>For this purpose, it employs low-level techniques that determine how available disk memory will be used, including the implementation of disk structures and the formatting of memory blocks, among others.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/Z2OaqmxiH20" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p> </p>
<h4 id="heading-6-implementation-of-applications-and-security-views-permissions-procedures">6. Implementation of Applications and Security (Views, Permissions, Procedures)</h4>
<p>Finally, once the database is built, you can design new layers on top of it where you can install applications and services that facilitate the interaction with the database. That is, you can simplify its operation for the end user, for example by developing a web application in HTML, CSS, and JavaScript to obtain the data in a friendly way, instead of with SQL code.</p>
<p>Some of these layers are also oriented to guarantee the <a target="_blank" href="https://www.ibm.com/think/topics/data-security">security</a> of the data, establishing higher level access controls than the DBMS where the user must authenticate to access the data. You can also encrypt the data using some of the functionalities of these layers.</p>
<h2 id="heading-chapter-5-relational-model-structured-data">Chapter 5: Relational Model (Structured Data)</h2>
<p>Now that you understand some of the processes we use to design databases, we will focus on the simplest databases, which are those that operate with structured data. These databases are usually called <strong>relational</strong> or <strong>structured</strong>. They are formally designed using the relational model, which is the formalization of the conceptual level used to design this type of database.</p>
<p>The reason relational databases are the simplest lies in the nature of the data they usually store and the constraints imposed on them, as we will see now. We’ll discuss both the conceptual and logical design levels simultaneously, where the fundamental elements of this type of system are mainly represented.</p>
<p>It’s important to differentiate between how these elements are viewed from the conceptual level and from the logical level, as they essentially refer to very similar, and sometimes equivalent, concepts – but formally they are different concepts. In a relational database, the information is structured in entities related to each other and composed of a series of attributes, which is the conceptual view of the model.</p>
<h3 id="heading-table-relation">Table (Relation)</h3>
<p>As mentioned before, structured data is that which follows a rigid schema and is organized in the form of tables. So the fundamental component for storing information in a relational database is the table, which is sometimes also called a relation. This component is part of the logical design, since we define it in the DBMS. So whenever we deal with tables, we are referring to the logical design level.</p>
<p>Here’s an example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityID</strong></td><td><strong>Name</strong></td><td><strong>Country</strong></td><td><strong>Population</strong></td><td><strong>Area</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Madrid</td><td>Spain</td><td>3,223,000</td><td>604.3</td></tr>
<tr>
<td>2</td><td>Athens</td><td>Greece</td><td>664,046</td><td>38.96</td></tr>
<tr>
<td>3</td><td>New York</td><td>USA</td><td>8,398,748</td><td>783.8</td></tr>
<tr>
<td>4</td><td>Tokyo</td><td>Japan</td><td>13,929,286</td><td>2,191.1</td></tr>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>2,140,526</td><td>105.4</td></tr>
</tbody>
</table>
</div><h3 id="heading-schema">Schema</h3>
<p>The example <strong>City</strong> table above stores data about different cities. The table has a schema, which is a series of reserved data to describe the structure of the table. That is, the schema consists of the table name, which in this case is <strong>City</strong>, along with the name and type of all the attributes it has, corresponding to the columns.</p>
<p>For example, if we are storing cities in this table, the Name column corresponds to the Name attribute of each city, which is a property that city entities have, in addition to the <strong>associations</strong> between entities, which in certain contexts are also called <strong>properties</strong>. This attribute must have a type, such as string in this case, to determine what kind of data it will contain.</p>
<p>So the table name along with the names and types of the attributes form the schema of a table, which is mainly determined by user requirements. But it’s the database designers who decide how to model the domain entities, what attributes are necessary to include, and the types of each one.</p>
<h3 id="heading-tuple">Tuple</h3>
<p>In addition to a schema, a table also has an instance, which is the set of tuples it contains at a given moment in time. Here, by tuple, we mean a row of the table, as we can mathematically view it as a tuple <strong>(value1, value2, value3…)</strong> where all the values for a certain city are present for all the table's attributes.</p>
<p>A peculiarity of the instance is that there can never be multiple identical tuples. This means, in this case, that there can’t be two or more cities that have the same values for all attributes at the same time. This restriction is imposed in the pure relational model, although we will see in practice that this restriction may not be followed to facilitate certain tasks.</p>
<p>This is the case because, in the pure relational model, the instance is considered a set of tuples, and mathematically, a set can’t have repeated elements. But in the practical implementation we will see, the instance is formally modeled with a multiset that does allow duplicates, as each tuple is internally associated with a value indicating how many times it’s repeated in the multiset.</p>
<h3 id="heading-attribute-domain">Attribute Domain</h3>
<p>Previously, we mentioned that each attribute has a domain, which allows the DBMS to determine how the data in that column will be stored. But we might have an attribute like <strong>Population</strong> where it doesn't make sense to store negative numbers, similar to Area.</p>
<p>To prevent these situations, the domain of the attribute can be restricted. For example, if we set Population to have only the INTEGER data type by default, it can take any value from the set/domain of integers. But if we only want it to take positive values, we need to add a constraint (which we’ll discuss later) so that the possible values for that attribute, meaning its domain, are only all positive integers.</p>
<h3 id="heading-derived-attribute">Derived attribute</h3>
<p>A special case of attributes is derived attributes. Their value is not stored, but is rather calculated from the value of other attributes.</p>
<p>Continuing with the example of the <strong>City</strong> table, suppose we have an attribute <strong>Density</strong> that should indicate the population density of a city. In this case, we can define it as a derived attribute, instead of calculating the values beforehand and inserting them into the database. Thus, every time <strong>Density</strong> is queried, the operation <strong>Population/Area</strong> will be performed, returning the value to the user in the corresponding tuple.</p>
<p>We can see a clearer example of this if we have an attribute BirthDate and we want to calculate the value of another attribute like <strong>Age</strong>. Here, we can calculate the attribute <strong>Age</strong> directly from <strong>BirthDate</strong> as if it were a <strong>"view"</strong> on that attribute. That is, we can see a birth date as if it were an age, from which we can derive the value of the attribute <strong>Age</strong>. We’ll discuss the concept of a view later in more detail at the implementation level.</p>
<p>Before moving on to the representation at the conceptual design level of a table, it's important to understand why a table is sometimes called a <a target="_blank" href="https://en.wikipedia.org/wiki/Relation_\(database\)">relation</a>. A relation is a subset of the <a target="_blank" href="https://en.wikipedia.org/wiki/Cartesian_product">Cartesian product</a> of the domains that the attributes have, but you can understand it more simply as a set of tuples that comply with a defined schema. For example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Letter</strong></td><td><strong>Number</strong></td></tr>
</thead>
<tbody>
<tr>
<td>A</td><td>1</td></tr>
<tr>
<td>A</td><td>2</td></tr>
<tr>
<td>B</td><td>1</td></tr>
<tr>
<td>B</td><td>2</td></tr>
</tbody>
</table>
</div><p>In this table, we can assume that the attributes <strong>Letter</strong> and <strong>Number</strong> have the domains <strong>{A, B}</strong> and <strong>{1, 2}</strong> respectively, so the entire set of possible tuples we can form with these domains are the tuples shown in the table itself.</p>
<p>These tuples come from the <strong>Cartesian product</strong> of both domains. So if we had larger domains, we would get a much broader cartesian product. A subset of its tuples is called a relation, and we can associate it as the instance of a table, which is why the term relation is sometimes used to refer to what is actually a table.</p>
<h3 id="heading-conceptual-representation">Conceptual Representation</h3>
<p>Putting this aside, it's not as important to focus on formal details like the name <strong>relation</strong>, but rather to understand the structure of a table and how data is stored in it. So far, everything we've seen about tables refers to the logical design level, which is where we actually work with tables. But at the conceptual level, there is an element very similar to a table called an <strong>entity</strong>.</p>
<p>According to the conceptual level, a relational database is a set of entities, where each one can be likened to a table. Each entity has a series of <strong>attributes</strong>, each with a <strong>domain</strong>, where instead of attribute, it’s usually called a property at the conceptual level.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751733945183/6d737d7b-f6f3-42af-ae91-3fae793524a0.png" alt="Entity City represented in an entity-relationship diagram. Image by author. " class="image--center mx-auto" width="252" height="254" loading="lazy"></p>
<p>Following the example of the City table from before, at the conceptual level, there is an entity called City, shown above in a <a target="_blank" href="https://www.freecodecamp.org/news/uml-diagrams-full-course/"><strong>UML (Unified Modeling Language)</strong> entity-relationship diagram</a>, which is the most common way to formally represent this type of information.</p>
<p>Sometimes we can use <a target="_blank" href="https://www.freecodecamp.org/news/crows-foot-notation-relationship-symbols-and-how-to-read-diagrams/"><strong>Crow's foot</strong></a> notation for the diagram, but here we’ll use the same notation as a class diagram in software engineering for simplicity. It’s equivalent, which is why entities are sometimes called classes.</p>
<p>To correctly understand what an entity is, think of it as if it were the schema of the table, or rather a class in object oriented programming that serves as a template to instantiate tuples. Just keep in mind that at the conceptual level they aren’t called tuples but rather instances or occurrences of an entity.</p>
<p>Intuitively, we can see it as if the attributes represented in the entity were the actual values of the first row of the equivalent table – that is, its schema. In this way, if we have a schema (that is, a template), we can create instances of that entity/schema/template simply by assigning values to those attributes. So when we assign values to the properties of an entity, we have an entity occurrence, which at the logical level we can see as a tuple.</p>
<p>For example, the entity <strong>City</strong> can be "instantiated" in a "tuple" like <strong>[5, Paris, France, 2140526, 105.4]</strong>. But at the conceptual level we should call it an <strong>occurrence</strong> instead of a tuple, since “instance” might cause confusion with the concept of instance we discussed earlier at the logical level.</p>
<pre><code class="lang-markdown">Entity: [CityID,Name,Country,Population,Area]    ---&gt;    Tuple=Occurence: [5,Paris,France,2140526,105.4]
</code></pre>
<p>So every time we see a box with a name and properties in an entity-relationship diagram, it refers to an entity that is logically equivalent to a table.</p>
<p>Regarding the concept of an instance we saw earlier, here it’s called an <strong>entity set</strong>, and it contains all the existing occurrences of that entity at a given point in time. In the diagram, we only see the template, not the set with the occurrences of that entity (think of the tuples of a table). In other words, the diagram at the conceptual level is used to see how the database is structured, not to see its specific instances or occurrences, which are more related to the logical level.</p>
<p>Regarding notation, in the entity-relationship diagram, the entity is represented in a box where all its properties (attributes) are listed by name and type. Here, the type does not have to match exactly the type offered by the DBMS in the logical design, as a translation from the conceptual to the logical level is done later, as we saw before.</p>
<p>To the left of each attribute, a <code>-</code> is usually placed to indicate that it’s a private attribute. But this concept is not relevant in this database context, as it comes from the uses given in software engineering to the class diagram notation we use here.</p>
<p>Lastly, attribute names are usually all in lowercase, although according to the style guide you follow, this can vary – like here, where we allow uppercase to minimize changes to attribute names when translating to logical design.</p>
<h3 id="heading-repeating-group">Repeating Group</h3>
<p>Once you know what an entity, or table, is, and that the database is a set of them related to each other, you’ll need to consider an important restriction about the table itself as a storage structure.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityID</strong></td><td><strong>Name</strong></td><td><strong>Country</strong></td><td><strong>Temperature</strong></td></tr>
</thead>
<tbody>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>7,44,20,90,1</td></tr>
</tbody>
</table>
</div><p>For example, if we have a City table similar to the one above where we only want to record the temperatures of the city at different points in time, the first option we might consider is to store all the temperatures that each city has or has had in a single Temperature attribute, all together.</p>
<p>But this is not allowed in structured databases for efficiency reasons (as well as formally, which you’ll see later). Specifically, this situation is known as a repeating group, and it occurs when we have to store an indeterminate number of values in an attribute.</p>
<p>For example, if we only need to store a maximum of 5 temperatures that a city can have, we could make the data type of Temperature an array of integers with a length of 5, which would be filled as we get temperature measurements. But if we don't know how many temperatures we will measure, we can’t set an upper limit on the size of the value we are going to store, so we can’t define a specific size for the length of the data type of that attribute. This creates a repeating group.</p>
<p>Anyway, even if we could set a size for data structures like an array, they are usually not allowed due to the uncertainty of the size the developer might set for that array (also considered a repeating group).</p>
<p>At the same time, this uncertainty is the reason why <strong>repeating groups</strong> pose a problem for the physical implementation of the database. Since we don't know how much space we’ll need to represent them, we might end up wasting lots of memory trying to manage this uncertainty, as well as <a target="_blank" href="https://stackoverflow.com/questions/3770457/what-is-memory-fragmentation">fragmenting</a> it, or complicating the implementation logic in an attempt to minimize the impact of this waste and memory fragmentation.</p>
<h4 id="heading-how-to-avoid-a-repeating-group">How to avoid a repeating group</h4>
<p>One way to solve the problem of repeating groups is to store each temperature measurement in a separate tuple. If all measurements can’t be stored in a single attribute value, then one option is to duplicate the information of the other attributes to create multiple tuples, each storing a specific temperature measurement.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityID</strong></td><td><strong>Name</strong></td><td><strong>Country</strong></td><td><strong>Temperature</strong></td></tr>
</thead>
<tbody>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>7</td></tr>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>44</td></tr>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>20</td></tr>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>90</td></tr>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>1</td></tr>
</tbody>
</table>
</div><p>As you can see, we have duplicated information to store each temperature measurement in a tuple, which avoids accumulating them all in a single value of the same tuple. But repeating data creates (unnecessary) redundancy in the database, which is a problem.</p>
<p>Redundancy is not an issue in all situations, as it can sometimes be good for ensuring data availability. But in this case, we can see that it’s it’s completely unnecessary. First, because it greatly increases the space needed to store city data by repeating the city’s information. Also, because having city data repeated so many times means that every time these data need to be modified, you’ll have to make changes to all tuples recording the temperatures, causing operations to take too long. And if the schema is modified to add or remove attributes, all data in their respective columns must be deleted – so if there is a lot of repeated data in them, those operations will also have high latency.</p>
<h3 id="heading-data-inconsistency">Data Inconsistency</h3>
<p>On the other hand, if in the previous example we insert a temperature measurement and for some reason an error occurs during the operation, we might end up in a situation like the following:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityID</strong></td><td><strong>Name</strong></td><td><strong>Country</strong></td><td><strong>Temperature</strong></td></tr>
</thead>
<tbody>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>7</td></tr>
<tr>
<td>5</td><td>Paris</td><td>China</td><td>44</td></tr>
</tbody>
</table>
</div><p>Here you can see that when inserting the measurement with a temperature of <strong>44</strong>, an error occurred, and the tuple was recorded with an incorrect <strong>Country</strong> value. This is not common, but if we choose to solve the repetitive group problem this way, we will be inserting duplicate values more often than necessary, making it more likely for these types of errors to occur.</p>
<p>Having the same information duplicated but with contradictory values indicates that our database has an inconsistency. This happens when the same information is duplicated in various places in the database, and the values are contradictory, such as in this example where we have multiple temperature measurements for what appears to be the same city but with the incorrect country value.</p>
<p>To ensure that it’s an inconsistency, we should look at the key values that uniquely identify each tuple, which we will discuss later. But intuitively, we need to focus on those attribute values that allow us to uniquely identify a tuple. If those values repeat in several tuples and there is some inconsistency in the other attributes, then we have an inconsistency.</p>
<p>On the other hand, if in the last example the <strong>Country</strong> value of the second tuple were <strong>"France,"</strong> we wouldn't have any inconsistency, even though the temperature values don't match. So it's important to understand that inconsistency mainly depends on the schema's semantics, meaning what each attribute signifies.</p>
<p>Finally, to solve the problem of repetitive groups, you’ll typically need to refine the schema – that is, to transform it. In this specific case, we’ll perform a normalization operation, which we’ll see how to do later. This involves separating a table like the one we had before with duplicated information into several tables:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityID</strong></td><td><strong>Name</strong></td><td><strong>Country</strong></td></tr>
</thead>
<tbody>
<tr>
<td>5</td><td>Paris</td><td>France</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>ReadingID</strong></td><td><strong>CityID</strong></td><td><strong>Temperature</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>5</td><td>7</td></tr>
<tr>
<td>2</td><td>5</td><td>44</td></tr>
<tr>
<td>3</td><td>5</td><td>20</td></tr>
<tr>
<td>4</td><td>5</td><td>90</td></tr>
<tr>
<td>5</td><td>5</td><td>1</td></tr>
</tbody>
</table>
</div><p>Now there is a <strong>City</strong> table very similar to the original, but with the difference that it only stores a record of the existing cities, not the temperatures recorded in them.</p>
<p>Also, there is another table we can call Readings, which contains the temperature measurements for each city. In this table, each tuple contains a measurement and an identifier that determines the city where the measurement was taken, which in this case is <strong>CityID</strong>.</p>
<p>For example, if the measurement was taken in Paris and that city has a CityID value of 5, then the CityID in the <strong>Readings</strong> table will be 5 for the measurements of that city. This avoids duplicating all the city information as happened before.</p>
<p>By doing this, we avoid the potential inconsistency problems that arose before, and we also save disk space by not duplicating unnecessary information. More importantly, it prevents the appearance of the repetitive group.</p>
<p>For this, we have had to "complicate" or rather enrich the database schema to some extent, meaning the tables that compose it and the schemas that form it. But the complexity in structured databases doesn’t come from being structured, but from the domain being modeled and its operations. In other words, the relational model of structured data is not complex by itself, as it is simply a model. What truly causes complexity is how we use that model to reflect the domain requirements.</p>
<h3 id="heading-entity-associations">Entity Associations</h3>
<p>In the context of conceptual design, a relational database is not only made up of entities (tables), as this only allows us to model the existence of "objects" in the domain. Most of the time, these objects will have associations with each other, meaning they will be related.</p>
<p>So, in conceptual design, we have the concept of <strong>entity association</strong>, which describes how "objects" are linked to one another. This is essential for reflecting the actual structure of the information.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751783067882/835a4c1c-1913-4847-9649-f2082d19d410.png" alt="Entity-relationship diagram showing entities City and Person, where each city can have one or more people living in it. Image by author. " class="image--center mx-auto" width="891" height="337" loading="lazy"></p>
<p>For example, in a domain, we can have entities like the ones above, <strong>City</strong> and <strong>Person</strong>. These model the existence of people and cities in the domain. But besides the existence of the entities themselves, it's possible that they have relationships with each other that we can model in our diagram – such as a person living in a certain city.</p>
<p>In this case, we use an association to allow a person in our system to live in a city, meaning we use an association to model that relationship between both entities.</p>
<p>At first glance, we can see that the association is represented in the entity-relationship diagram as a relationship established between entities – but it's important to remember that entities are "templates" from which occurrences of entities are generated when implementing the system (that is, specific tuples). So when we introduce an association at the conceptual level, we have to view it in terms of the tuples that will later be generated from the related entities.</p>
<p>For example, here the relationship can occur between one occurrence (tuple) of a city and many occurrences of a person, since many people can live in a city. But the reverse may not be true depending on the domain requirements, which may determine that a person (occurrence of the entity <strong>Person</strong>, or tuple of the table <strong>Person</strong>) can only live in one city, as we’re assuming in this case.</p>
<h4 id="heading-association-role">Association Role</h4>
<p>In an entity-relationship diagram, the notation of the association is usually represented with a line connecting two entities, known as a binary association. But there are higher-degree associations (which we won't cover here for simplicity) that relate an arbitrary number of entities in a single association.</p>
<p>A role and a direction are usually added to this line to clarify the semantics of the relationship. The role is a word or phrase written above the association line and denotes the role that an entity has in the represented relationship with respect to the direction defined alongside the role.</p>
<p>For example, in the diagram below we have an association between a person and a city. So in the association, the role given to the person is "lives" in the city with which they are associated, as the direction has been defined from the person to the city with the arrow next to the role. In other words, in this relationship between both entities, the function that the person performs is to "live" in the city with which they are associated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751789958682/1f5aa10e-3120-49a1-a7f0-9791a3f2e25e.png" alt="Entity-relationship diagram showing City and Person, where each city has one or more residents. Image by author." class="image--center mx-auto" width="921" height="366" loading="lazy"></p>
<p>This role doesn't need to be included in all associations, nor is it necessary to establish a direction. But in some cases, it helps us understand the diagram and the domain, which is the goal of the diagram itself.</p>
<p>Also, the role isn't rigid and can be modeled in many ways. For example, in this case, we can reverse the direction of the association and say that the city has the role of "having residents," which are the people it’s associated with. This would model the existence of people living in the city.</p>
<h4 id="heading-cardinality">Cardinality</h4>
<p>Continuing with the different elements of an association, we have <strong>cardinality</strong>, which describes how many <strong>occurrences</strong> (tuples) of one entity can or should be associated with how many occurrences of another entity. We represent this with numbers on both sides of the association line that denote the <strong>minimum</strong> and <strong>maximum</strong> cardinality, respectively.</p>
<p>To understand this using the previous example, we know that a person can only live in one city, so a person entity will be associated with at most one city. In turn, we can also assume that every person must live in some city, meaning there are no people living in the woods outside of society. So since every person must be associated with exactly one city, the multiplicity we put on the city entity side is 1…1, which is simply written as 1.</p>
<p>Here, the first 1 is the minimum cardinality, indicating that each person must be associated with at least one city, while the other 1 is the maximum cardinality, indicating that each person can be associated with at most one city. For simplicity in the diagram, the number 1 is usually used to denote both cardinalities at once. Also, when we talk about people and cities here, we are referring to the actual occurrences of the entities, which at a logical level are tuples.</p>
<p>If we look at the other side of the association, we see it has <a class="post-section-overview" href="#heading-the-role-of-data-in-todays-digital-world">The Role of Data in Today's Digital World</a> (sometimes called multiplicity) 1…*, where 1 is the minimum cardinality, indicating that a city must be related to at least one person. This means that in all the cities within our domain, there must be <strong>at least</strong> one inhabitant.</p>
<p>On the other hand, the * in the <strong>maximum cardinality</strong> is a way to denote that there is no specific value that must be given to that cardinality – it can be any amount. This means a city can be associated with an arbitrary number of people, indicating that the cities in our domain can have any number of inhabitants.</p>
<p>Since the asterisk denotes any, unbounded amount, we don't have to worry about it being consistent with the minimum cardinality. That is, even if we set the minimum cardinality to 1, by using an asterisk for the maximum, we are indicating that the maximum can be any number from 1 to infinity. This means that cities will have at least one inhabitant and at most an infinite number.</p>
<p>From the <strong>minimum cardinality</strong>, we can introduce the concepts of <strong>optionality</strong> and <strong>obligation</strong>. For example, before we had minimum cardinalities greater than 0, which indicate that a person must always be associated with a city, or a city must always be associated with at least one person. This means that when occurrences of these entities are created, they must meet the restriction imposed by the minimum cardinality of being associated with some occurrence of the other entity. So at creation, it must be directly associated with the other entity that indicates the association, to respect the minimum cardinality.</p>
<p>To see this at the logical design level, we first need to introduce the tools of that level with which associations are implemented – although for now, we can view it by thinking in the object-oriented paradigm, where if we instantiate a person object, it must have a <strong>reference</strong> to another city object, and vice versa.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751792178992/276f82ef-6895-487c-b7a0-7f1d01d9525f.png" alt="Entity-relationship diagram showing City and Person entities. Image by author. " class="image--center mx-auto" width="899" height="285" loading="lazy"></p>
<p>Regarding optionality, let's consider another possible case where a city can have an arbitrary number of residents, including being uninhabited, meaning empty, since we have set the minimum cardinality to 0 and the maximum to *. This can also be represented more simply by just using the asterisk, indicating an arbitrary amount including 0.</p>
<p>Now, let's also assume that a person can live in one or two cities, so their corresponding cardinality is modified to 1..2, indicating that a person must be associated with at least one city and at most two cities simultaneously at any point in their life cycle.</p>
<p>This occurs since the entity-relationship diagram is <strong>instantaneous</strong>, not <strong>historical</strong>, which means that what we see in the diagram is an instantaneous representation of our domain, not a representation of its life cycle or evolution over time.</p>
<p>So when we see that an association has a multiplicity of 1..2 as in this case, we must think that at any given moment, a person must be associated with at least one city and at most two cities. We shouldn’t think that a person must have been related to at least one city and at most two cities throughout their whole lifetime.</p>
<p>Here we can see that a city may have no residents due to the minimum cardinality of 0 that we have set on the person side, indicating that a city may not be associated with any person. With this, we can model optionality, which refers to allowing an association not to occur. That is, when we create a city from its entity (template), we don't have to associate it with a person, since it can be associated with 0 people at minimum. This means that it's not necessary to add a reference to any person because a city may be abandoned and have no residents.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751792219256/f668bb15-db83-492b-ac95-c788ee6c8c19.png" alt="Entity-relationship diagram showing City and Person entities. Image by author. " class="image--center mx-auto" width="917" height="316" loading="lazy"></p>
<p>To correctly understand optionality, we can modify the example again so that a person can be associated with either no city or one city, indicating that the person may not live in any city or may live in one. Also, on the other side of the association, we also change the maximum cardinality to 500, indicating that a city can have an arbitrary number of residents between 0 and 500, meaning it can be associated with any number of people from 0 to 500, inclusive. This means having residents is optional.</p>
<p>With this, it should be clear that we can set cardinalities as we want according to the domain and requirements – but we always need to ensure they are correct and make sense. For example, you can’t set a maximum cardinality that is strictly less than the minimum cardinality.</p>
<p>In this case, something peculiar happens: on both sides, we have a minimum cardinality of 0, meaning we have optionality. So when we create new instances of the entities, they don't have to be associated with instances of entities on the other side of the association. We can see this as if the association we modeled is entirely optional.</p>
<p>To conclude, although we can set any number for minimum and maximum cardinalities depending on the modeled domain, the most common ones are 1..1, 1..M, or M..N, where N and M can be arbitrary numbers, including 0 in the case of N..M, as long as they aren’t both 0 at the same time (because in that case, the association could not exist).</p>
<h4 id="heading-recursive-associations">Recursive Associations</h4>
<p>On the other hand, an association does not necessarily have to relate multiple entities. We can use it to model a relationship between occurrences of the <strong>same entity</strong>. For example, if we want to model the friendship relationship between people in our domain, we can use a <strong>recursive association</strong> in the entity Person:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751795267979/91b3c5e3-5642-40eb-a270-721ceb8cd93a.png" alt="Entity-relationship diagram where Person has a friendship relationship with itself. Image by author. " class="image--center mx-auto" width="451" height="422" loading="lazy"></p>
<p>First of all, it’s very convenient to establish a role in recursive associations, as it’s the simplest way to represent their semantics so we can easily understand them when looking at the diagram.</p>
<p>But in this case, it’s not as useful to specify the direction of the association since the friendship relationship can be considered symmetric. Here, we have modeled the friendship relationship so that one occurrence of Person can be associated with any number of other occurrences of <strong>Person</strong>, including none, which indicates that in our domain, a person (occurrence of Person entity) can have an arbitrary number of friends, including 0.</p>
<p>Regarding notation, it makes no difference to use 0..* or *, as they indicate the same thing – but we should always use the shortest and simplest notation to understand.</p>
<p>In summary, a recursive association is simply one where both related entities are the same. In this case, the friendship association necessarily relates people to people, meaning it establishes which people are friends with each other.</p>
<h4 id="heading-associative-entity">Associative Entity</h4>
<p>Now that we know what associations are, let’s learn about the concept of an <strong>associative entity</strong>. In some cases it’s also called a <strong>property</strong> just like the <strong>associations</strong> themselves. In the following example, there are cities in a domain that can host from 1 to 500 inhabitants, as long as the implicit restriction of having at least one resident is respected. Also, a person can live in an arbitrary number of cities between 0 and 3.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797687686/758c9f22-ceb2-4c01-a0be-34219c1ee592.png" alt="Entity-relationship diagram showing City and Person entities. Image by author. " class="image--center mx-auto" width="1366" height="405" loading="lazy"></p>
<p>The above conceptual diagram would model this situation. As it stands, we can’t store any information about the person's stay in the city, meaning we can’t save information like the dates they started living in that city or moved to another. If we try to do so, we’ll have several options that lead to certain problems in the database.</p>
<p>On one hand, we could choose to add attributes like <strong>StartDate</strong> and <strong>EndDate</strong> to the <strong>Person</strong> entity to determine the respective dates when a person started living in a city or moved to another. But this wouldn't even work if the multiplicity 0..3 of the city were 1..1, because over the person's lifetime, even though they can live in only one house at a time in the 1..1 case, it's possible that the person moves several times throughout their life. This would require multiple pairs <strong>(StartDate, EndDate)</strong> to be recorded. So since we need to store multiple pairs of these dates, a repeating group would be generated in the respective properties (attributes), forcing us to refine the schema.</p>
<p>On the other hand, we could store those attributes in the <strong>City</strong> entity, but we would encounter a very similar problem here. We would have to record multiple pairs of <strong>(StartDate, EndDate)</strong> values for each person, with the added complexity that a city can have many residents. This would also create a repeating group, along with the issue of associating each <strong>(StartDate, EndDate)</strong> pair with the correct person.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751797354936/4c721372-a21c-4aa3-8ddb-29d81ecbc830.png" alt="Entity-relationship diagram where City and Person are linked through Residence. Image by author. " class="image--center mx-auto" width="1300" height="457" loading="lazy"></p>
<p>To address this situation, ideally, we should be able to store these attributes within the association itself. This way, when a person starts living in a city, their association would contain these attributes, and they could record the date the person started living in the city as well as the date they stop. This value (when they stop living in the city) can be left blank or set to "<strong>NULL</strong>" until they actually leave and the association is no longer valid.</p>
<p>To achieve this, at a conceptual level, associative entities are used. These are entities whose main purpose is to allow our database to store information about the associations between entities.</p>
<p>As you can see, associative classes are <strong>"related"</strong> to associations between entities, not directly with other entities, and they don't have multiplicity or roles. This is because they exist only when the association between several entities is actually established. For example, when a person starts living in a city, they associate with a city, and this association relates to an occurrence of the associative class where the respective attributes like StartDate and EndDate are stored.</p>
<p>So for each person-city association we have, there will also be an occurrence of the <strong>Residence</strong> entity with the values of its corresponding properties. Also, keep in mind that this association doesn't exist all the time, as the person may stop living in that city – so the association itself may cease to be valid or, rather, cease to exist conceptually.</p>
<p>But depending on how we translate the relational diagram to the logical design of the database, we might want to record the StartDate and EndDate values that the occurrence of the respective associative entity had.</p>
<p>If we want this, we will need to specify it in the logical model of the database or in the conceptual model with a note in the diagram's margin. This is because, at a conceptual level, there are no specific tools beyond notes to specify these kinds of details, which are more related to the logical design.</p>
<h4 id="heading-aggregation-and-composition">Aggregation and Composition</h4>
<p>Since a <strong>UML entity-relationship diagram</strong> is used at the conceptual level, there are modifiers we can use in the associations to give them a particular meaning. But this has no effect at the logical level – meaning the introduction of these modifiers in the conceptual diagram doesn't imply any kind of change at the logical level. They are simply used to clarify the details of the modeled domain.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751810875604/7b9044be-8d9b-43f2-8d80-61a190c23b6b.png" alt="Entity-relationship diagram where City is made up of instances of Person and each person consists of a single Brain. Image by author. " class="image--center mx-auto" width="1017" height="669" loading="lazy"></p>
<p>On one hand, an association can be of the aggregation type, like between Person and City, where aggregation is denoted by an unfilled diamond and signifies that a city can be composed of people. This means that the entity with the diamond is composed of entities on the other side of the association.</p>
<p>Also, in the specific case where we create and destroy entity occurrences at the same time, the aggregation becomes a composition, denoted by a filled diamond. It then works the same way as aggregation – the only difference being the meaning it conveys.</p>
<p>For example, in the above diagram we have modeled that a person is composed of a single brain. Since a person's brain can’t exist independently of the person, the association is denoted as a composition. This is because aggregation would allow the brain to exist independently, which is not possible.</p>
<p>If we look at it inversely, the composition does not prevent the person from existing without being related to a brain, although the 1..1 cardinality we have placed on both sides models this situation, requiring all people to have exactly one brain.</p>
<p>The important thing to understand is that both composition and aggregation are just associations with additional meaning. This means that they don’t influence the logical design of the database itself, much less at the implementation level.</p>
<h3 id="heading-generalization-and-specialization">Generalization and Specialization</h3>
<p>Another feature of the relational model is that, besides modeling associations between entities as we have seen, it can also model other types of relationships between entities. This can be useful in many situations.</p>
<p>For example, if we have a domain where there are people who can be customers or employees, we can use a generalization and specialization relationship like the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751812519420/7e7fe801-22df-4411-862d-e74a1b56e263.png" alt="Entity-relationship diagram with inheritance where Client and Employee are subclasses of Person. Image by author. " class="image--center mx-auto" width="841" height="646" loading="lazy"></p>
<p>Generalization-specialization relationships work the same way as in object orientation. We have a class like <strong>Person</strong> with a set of attributes, allowing for specializations of that class like <strong>Client</strong> or <strong>Employee</strong>, where all instances are also people but with more specific attributes.</p>
<p>In the case of Client, it’s a specialized entity derived from the Person entity, so it inherits all the attributes of its parent entity since a client is also a person. In addition to these inherited attributes, it has others specific to being a client. So when an instance of the Client entity is created, think of it as having all the attributes of both Client and Person at the same time. The same happens with Employee but with its respective attributes.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751814124946/fa1daef2-46b0-47a8-8f62-c32642d5a165.png" alt="Venn diagram where Client and Employee are subsets of Person, with possible overlap. Image by author. " class="image--center mx-auto" width="666" height="697" loading="lazy"></p>
<p>If we look at it from a <a target="_blank" href="https://en.wikipedia.org/wiki/Set_theory">set theory</a> perspective, first we have the entity Person, which gives rise to a set of entities that are people, meaning the occurrences of that entity. Within this entire set, it's possible that, in addition to occurrences of Person, there could be occurrences of Client, since every client is a person. So in the set of people, there will be some who are clients. This also happens with Employee, where in the set of people, there will also be employees, with all of them being people.</p>
<p>Also, nothing prevents a person from being both a client and an employee at the same time, so there will also be elements in the set that are both a client and an employee. But this detail is closer to the logical design of the database than to the conceptual representation of generalization and specialization presented here. In this case, these names indicate that classes like Person are more general than Client, which are their respective specializations.</p>
<h3 id="heading-entity-association-pitfalls">Entity Association Pitfalls</h3>
<p>When we are in the conceptual design stage and create the entity-relationship diagram, it's common to encounter association structures that initially seem correct but, when implemented in a DBMS, lead to ambiguities or unexpected problems that require us to refine the conceptual design. One of these structures is the <strong>Fan Trap</strong>:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751814711606/798ec2c1-20dc-47d0-905b-acdc8becc39f.png" alt="Fan trap example. Image by author." class="image--center mx-auto" width="1553" height="326" loading="lazy"></p>
<p>The Fan Trap appears when we have a "central" class like <strong>City</strong> that is associated in a "fan" shape with two others, Person and Pool, where each has maximum cardinality on its side. This means a city can be associated with many people and many pools at the same time.</p>
<p>This situation is initially correct, but the problem arises when we want to know which people from a certain city go to which pool. This becomes complicated because if we are given a certain person, we can know their city, as we have defined that a person can only live in one city. But the city can have many pools, so we don't know which specific pool the person goes to. We can only know which pools the city has where they live. Also, the city might have no pools, given the minimum cardinality of 0 on the pool side.</p>
<p>On the other hand, if we are given a pool, we can determine which city it belongs to. Then with that city, we can find out the group of people living there, which we can use to solve the previous question – but in a much more complex way.</p>
<p>To solve this problem, there are many alternatives, although the simplest in this case is to add an explicit association between <strong>Person</strong> and <strong>Pool</strong> to model the fact that a person goes to a pool. But if we’re not going to make these types of queries frequently, it might not be worthwhile to complicate the diagram.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751818303502/70eecb3e-f2f1-4989-9348-afb81fb71346.png" alt="Chasm trap example. Image by author. " class="image--center mx-auto" width="1552" height="353" loading="lazy"></p>
<p>There is also the <strong>Chasm Trap</strong>, which is similar to a Fan Trap but with important differences. For example, in the diagram above, you can see a Chasm Trap. It occurs when we are given a city and asked to find the pools located in it. The only thing we can do is get the group of people living in that city and, from that group, identify some of the pools the city has.</p>
<p>In other words, each pool may or may not have an association with a person, since not all people go to the pool. So, if we try to find all the pools in a city by simply looking at the pools the city's residents go to, we might encounter situations where no resident of the city goes to the pool. Thus, all the pools will take advantage of the 0..30 cardinality on the Person side to not have any associated people, meaning no one goes to those pools.</p>
<p>So if there are pools that no one visits, we won't be able to find them through a group of people. This means that, given a city, we might not know all the pools it has, because if we solve the query this way, we can only be sure of knowing the pools that the city's residents visit. But if there's a pool that no one visits, then that pool won't be accessible through a person. In other words, people won't see those pools, since the 1..* relationship requires them to visit some pool – but it can still happen that no one visits a certain pool.</p>
<p>The solution to this problem is practically the same as for the Fan Trap, although there are many alternatives depending on the domain and requirements. There are also more situations that can lead to these problems or ambiguities which you can <a target="_blank" href="https://koushik-dutta.medium.com/avoiding-pitfalls-a-guide-to-sql-traps-and-how-to-solve-them-acdc3a95c74f">read more about here</a>.</p>
<h3 id="heading-keys">Keys</h3>
<p>So far, we have talked about entities and associations at the conceptual level, as well as tables at the logical level. Continuing with the logical level, we have not yet introduced any mechanism to uniquely identify the tuples contained in a table. This can be very useful since tuples are data points – that is, occurrences of an entity, like people, cities, and so on.</p>
<p><strong>Uniquely identifying</strong> them makes it easier to perform operations or queries on the table. It also allows us to implement associations between entities at the logical level through references between tables.</p>
<p>Keys are sets of attributes used to uniquely identify each tuple in a table. The combination of values in these attributes must be different for every tuple, so that no two tuples are the same.</p>
<p>To understand this concept, let’s start by looking at the different types of keys and their main utility.</p>
<h4 id="heading-superkeys">Superkeys</h4>
<p>Superkeys are sets of attributes that uniquely identify each tuple in a table. They are the most general type of key. As long as the combination of values for those attributes is unique for every tuple, the set of attributes qualifies as a superkey.</p>
<p>Here’s an example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>ID</strong></td><td><strong>SSN</strong></td><td><strong>Name</strong></td><td><strong>Birth</strong></td><td><strong>Email</strong></td></tr>
</thead>
<tbody>
<tr>
<td>30</td><td>74</td><td>Alice Johnson</td><td>1985-07-12</td><td>alice.johnson@example.com</td></tr>
<tr>
<td>22</td><td>59</td><td>Bob Smith</td><td>1990-03-05</td><td>bob.smith@example.org</td></tr>
<tr>
<td>95</td><td>10</td><td>Carol Davis</td><td>1978-11-23</td><td>carol.davis@example.net</td></tr>
<tr>
<td>21</td><td>32</td><td>David Brown</td><td>2001-01-30</td><td>david.brown@example.com</td></tr>
<tr>
<td>47</td><td>61</td><td>Emily Wilson</td><td>1995-09-14</td><td>emily.wilson@example.co.uk</td></tr>
</tbody>
</table>
</div><p>In this case, we have a table called <strong>Person</strong> where each row stores a person's data. Each person has a government <strong>ID</strong> number, as well as a <strong>Social Security Number (SSN)</strong>, name, and other details.</p>
<p>A possible superkey would be the attributes <strong>{ID, Name}</strong>, because among all the people that exist, no two people can have the same name and the same government ID number. But if we choose only <strong>{ID}</strong> as a <strong>superkey</strong> and try to uniquely identify all the rows in the table, depending on the data in the rows, we might encounter a situation where two people have exactly the same name, with identical first and last names. In this case, we couldn't uniquely identify both by their name alone.</p>
<p>So by including the ID in the superkey, we can differentiate between the two people/rows, as they can’t have the same government ID. We could also have chosen <strong>{ID, SSN}</strong> or even <strong>{SSN, Name}</strong> as a superkey, since the combinations of values in those attributes are very unlikely to repeat among different people. It’s impossible, for example, for multiple people to have the same name and Social Security Number.</p>
<p>Here’s another way to look at this: if we choose <strong>{ID, Name}</strong> as a superkey, then there can't be multiple rows in the table with the same ID and Name values. In other words, if we choose that superkey, it's because we are sure that this situation won’t occur, ensuring that all rows have a unique combination of values for the ID and Name attributes.</p>
<p>This mainly depends on the domain, as identifying a superkey formally is not simple. It involves knowing all the domains and associated constraints of the attributes in detail, as well as the functional dependencies between them (which we’ll discuss later).</p>
<p>In summary, although you can identify a superkey by formal methods, we won’t go into detail about them here. They’re usually not simple, as they combine techniques like closure or backtracking, which aren't useful to explain for correctly understanding the concept of a superkey. So for now, it's enough to focus on the semantics of each attribute and stick to those attributes that we know can't be repeated in multiple rows, like identifying codes of entities, names, or specific properties they might have, and so on.</p>
<p>Lastly, regarding the above table, we have seen some of the possible superkeys that can exist. But if we want to find all of them, we’ll first assume that the attributes with repeated values in several tuples are <strong>Name</strong>, <strong>Birth</strong>, and <strong>Email</strong>, since multiple people can have the same name, email, or birth date. Considering that <strong>ID</strong> and <strong>SSN</strong> do not repeat because they are government identifiers, we would have the following sets as superkeys, ordered by their size or cardinality:</p>
<ul>
<li><p><strong>Cardinality 1:</strong> {ID}, {SSN}</p>
</li>
<li><p><strong>Cardinality 2:</strong> {ID, SSN}, {ID, Name}, {ID, Birth}, {ID, Email}, {SSN, Name}, {SSN, Birth}, {SSN, Email}</p>
</li>
<li><p><strong>Cardinality 3:</strong> {ID, SSN, Name}, {ID, SSN, Birth}, {ID, SSN, Email}, {ID, Name, Birth}, {ID, Name, Email}, {ID, Birth, Email}, {SSN, Name, Birth}, {SSN, Name, Email}, {SSN, Birth, Email}</p>
</li>
<li><p><strong>Cardinality 4:</strong> {ID, SSN, Name, Birth}, {ID, SSN, Name, Email}, {ID, SSN, Birth, Email}, {ID, Name, Birth, Email}, {SSN, Name, Birth, Email}</p>
</li>
<li><p><strong>Cardinality 5:</strong> {ID, SSN, Name, Birth, Email}</p>
</li>
</ul>
<h4 id="heading-candidate-keys">Candidate Keys</h4>
<p>Next, we have candidate keys. Their main purpose is the same as superkeys, with the only difference being that in this case, they use the minimum number of attributes possible for identification.</p>
<p>For example, before, as a superkey, we could choose <strong>{ID, Name}</strong>, among other options. But that superkey contains the ID attribute, which represents the government identifier for each person, and we have legal assurance that it is unique for each person.</p>
<p>So, since we know that each person's ID is unique, as is their Social Security Number because it’s also a number related to government procedures, we can reduce the number of attributes needed to uniquely identify each tuple and choose a candidate key like <strong>{ID}</strong> or <strong>{SSN}</strong>. We could also consider <strong>{Email}</strong> as a candidate key, although we assume that several people could have the same email, so we do not count it as a candidate key.</p>
<p>As you can see, conceptually the candidate keys play the same role as superkeys, but here the goal is to achieve identification with fewer attributes, specifically with the minimum number possible. In this example, by considering candidate keys with a single attribute like <strong>{ID}</strong>, we have managed to uniquely identify tuples with the smallest possible number of attributes, since you can’t form any type of key with fewer than one attribute.</p>
<p>Also, to verify that a key is a candidate and not a superkey, you can check that there is no subset of attributes of the key that by itself forms a key.</p>
<p>For example, if we have a key like <strong>{ID, Name}</strong> and want to check if it is a candidate key, we just need to check all possible subsets of attributes it has, which are {ID} and {Name} (although there can be subsets with more attributes). And remember that several people can have the same name, but if we look at the subset {ID}, we will see that no person has the same ID as another.</p>
<p>So since there is a subset that can uniquely identify the tuples, it fulfills the fundamental property of any key. This means that the <strong>{ID, Name}</strong> we were checking is not a superkey, as there is a subset of its attributes that is a key.</p>
<p>If we repeat this process exhaustively, we are guaranteed to find a candidate key, that is, a minimal set of attributes that serves as a key to identify the tuples.</p>
<p>So basically, a candidate key is just a minimal superkey: it uniquely identifies each tuple, and if we remove any column from it, it no longer uniquely identifies tuples.</p>
<p>In practice, we rarely enumerate every superkey or worry about the labels. We just look for a set of attributes that uniquely identifies each tuple, preferably with as few attributes as possible. In design, at the logical level, we could define multiple candidate keys (and, implicitly, many superkeys), but the important step is choosing one candidate key as the <strong>primary key</strong> to uniquely identify tuples.</p>
<h4 id="heading-primary-keys">Primary Keys</h4>
<p>Once we have all the candidate keys that exist (since there can be several depending on the domain and tables we are dealing with), we need to select one of them as the <strong>primary key</strong> to implement in the DBMS. This way, we can have a key that uniquely identifies the tuples. In other words, a table can have many candidate keys, but these keys are subsets of attributes that we analyze theoretically.</p>
<p>To make them practical and actually identify the tuples in a table, we need to implement one of them in the logical model. Basically, we need to tell the DBMS which of all the candidate keys is the primary one we’ve selected for identification.</p>
<p>With this, we can infer that the name "candidate key" comes from the fact that there can be many minimal subsets of attributes with which we can identify the tuples. But in practice, we only use one of them, which is the one we indicate to the DBMS, that is, the primary key.</p>
<p>In the previous example, from all the superkeys <strong>{ID, Name}</strong>, <strong>{SSN, Name}</strong>, <strong>{ID, Email}</strong>, and so on, we can derive the candidates <strong>{ID}</strong> and <strong>{SSN}</strong>, from which we can choose <strong>{ID}</strong> as the primary. You shouldn’t always make this choice arbitrarily, even though you technically have the option to do so. Rather, you should consider the technical details of the implementation, as well as the semantics of the attributes that form the key to keep it easy to understand, among other factors.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751882614007/17c082cf-4d82-48ec-8595-bae0e7497236.png" alt="Entity-relationship diagram with the entity Person. Image by author. " class="image--center mx-auto" width="342" height="307" loading="lazy"></p>
<p>Even though the primary key is selected for use at the logical level, it can also be represented in the entity-relationship diagram at the conceptual level. If it consists of a single attribute, it’s marked with <strong>{id}</strong> next to its data type. But if the primary key is <strong>composite</strong> (meaning it’s made up of several attributes where each one is not enough to uniquely identify the tuples, but together with the other marked attributes it is), then all of them are marked with <strong>{ID}</strong>. As for candidate or superkeys, they aren’t specially marked in the diagram because there can be many.</p>
<h4 id="heading-alternate-keys">Alternate Keys</h4>
<p>Of all the candidate keys we have, we only choose one as the primary, leaving all the others aside. These keys that aren’t selected as primary are called alternate keys, and their main use is the same as that of a primary key: to uniquely identify the tuples in case the primary key is not accessible or it’s not convenient to use it.</p>
<p>You can also use alternate keys to improve the efficiency of certain operations or queries on the table, as indexes can be defined on them. But we won’t go into detail about this type of optimization technique here.</p>
<p>In our example, if the candidate keys were <strong>{ID}</strong> and <strong>{SSN}</strong> and we choose <strong>{ID}</strong> as the primary, then <strong>{SSN}</strong> will be the only alternate key we have.</p>
<h4 id="heading-composite-keys">Composite Keys</h4>
<p>Another type of key is a composite key, which is defined as a candidate key composed strictly of more than one attribute because each attribute alone is not enough to uniquely identify the tuples in the table.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityName</strong></td><td><strong>Country</strong></td><td><strong>Population</strong></td><td><strong>Area</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Madrid</td><td>Spain</td><td>3,223,000</td><td>604.3</td></tr>
<tr>
<td>Athens</td><td>Greece</td><td>664,046</td><td>38.96</td></tr>
<tr>
<td>Nantes</td><td><strong>France</strong></td><td>320,732</td><td>65.19</td></tr>
<tr>
<td>Tokyo</td><td>Japan</td><td>13,929,286</td><td>2,191.1</td></tr>
<tr>
<td>Paris</td><td><strong>France</strong></td><td>2,140,526</td><td>105.4</td></tr>
<tr>
<td><strong>San José</strong></td><td>Costa Rica</td><td>333,980</td><td>44.6</td></tr>
<tr>
<td><strong>San José</strong></td><td>USA</td><td>1,013,240</td><td>469.7</td></tr>
</tbody>
</table>
</div><p>For example, here we have a <strong>City</strong> table with information about cities around the world. As you can see, the attributes <strong>CityName</strong> and <strong>Country</strong> alone can’t uniquely identify each city, since there are cities in the world that share a country, like <strong>Nantes</strong> and <strong>Paris</strong>, and there are also cities with the same name that are located in different countries.</p>
<p>This means that we can’t use any of these attributes separately in a candidate key, as there are multiple cities with the same value in those attributes when viewed individually.</p>
<p>But if we look at them together and consider the composite key <strong>{CityName, Country}</strong>, we see that no city in our list located in the same country has the same name, so it meets the requirements to be a candidate key. It’s also a superkey, since all candidate keys are superkeys.</p>
<p>This way, we ensure that it’s indeed a composite key, which we can then select as the primary key. This is why sometimes in the definition of a composite key, the term primary key is used instead of candidate key.</p>
<h4 id="heading-surrogate-keys">Surrogate Keys</h4>
<p>So far, we have seen keys formed by choosing a set of attributes from a table that can uniquely identify tuples. But sometimes this may not be possible.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Name</strong></td><td><strong>Birth date</strong></td><td><strong>Email</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Alice Johnson</td><td>1985-07-12</td><td>alice.johnson@example.com</td></tr>
<tr>
<td>Bob Smith</td><td>1990-03-05</td><td>bob.smith@example.org</td></tr>
<tr>
<td>Carol Davis</td><td>1978-11-23</td><td>carol.davis@example.net</td></tr>
<tr>
<td>David Brown</td><td>2001-01-30</td><td>david.brown@example.com</td></tr>
<tr>
<td>Emily Wilson</td><td>1995-09-14</td><td>emily.wilson@example.co.uk</td></tr>
</tbody>
</table>
</div><p>For example, in this Person table, we have the same attributes as before except for <strong>ID</strong> and <strong>SSN</strong>, which were the only government identifiers we could use to uniquely distinguish people or tuples in the table.</p>
<p>Now, no matter which subset of attributes we choose, it can’t serve as a key, since we assume there could be multiple people with the same name, born on the exact same date, and using the same email address (this is an assumption here and may not be true depending on the modeled domain).</p>
<p>Since we can’t choose a key with the attributes we have, we need to artificially generate an attribute that can serve as a key. This attribute is known as a surrogate key, and it consists of an attribute that contains sequential numeric values for all the tuples. This means that to ensure each one has a unique value in this attribute, they are numbered from 1 to infinity with integers, guaranteeing the key property.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>SurrogateKey</strong></td><td><strong>Name</strong></td><td><strong>Birth</strong></td><td><strong>Email</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Alice Johnson</td><td>1985-07-12</td><td>alice.johnson@example.com</td></tr>
<tr>
<td>2</td><td>Bob Smith</td><td>1990-03-05</td><td>bob.smith@example.org</td></tr>
<tr>
<td>3</td><td>Carol Davis</td><td>1978-11-23</td><td>carol.davis@example.net</td></tr>
<tr>
<td>4</td><td>David Brown</td><td>2001-01-30</td><td>david.brown@example.com</td></tr>
<tr>
<td>5</td><td>Emily Wilson</td><td>1995-09-14</td><td>emily.wilson@example.co.uk</td></tr>
</tbody>
</table>
</div><p>In addition to this auto-incremental approach, where we can see that the surrogate key is an integer value that increases as tuples are inserted into the table, there is also the possibility of the attribute assigning each tuple a <strong>UUID (Universally Unique Identifier)</strong>, which is a <strong>128-bit</strong> binary data type usually represented as a string that allow us to assign a unique value to each tuple.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>SurrogateKey</strong></td><td><strong>Name</strong></td><td><strong>Birth</strong></td><td><strong>Email</strong></td></tr>
</thead>
<tbody>
<tr>
<td>e9e5a22b-d90c-4e5a-8d49-bbc24ff9335e</td><td>Alice Johnson</td><td>1985-07-12</td><td>alice.johnson@example.com</td></tr>
<tr>
<td>374d6cbe-fc29-4db0-91db-d21a1e2fef3c</td><td>Bob Smith</td><td>1990-03-05</td><td>bob.smith@example.org</td></tr>
<tr>
<td>57f182c5-47e2-4b71-b82c-63dc1795f9f5</td><td>Carol Davis</td><td>1978-11-23</td><td>carol.davis@example.net</td></tr>
<tr>
<td>a979dd61-daa4-4d88-a9f3-9a60c23d5b16</td><td>David Brown</td><td>2001-01-30</td><td>david.brown@example.com</td></tr>
<tr>
<td>179f4e15-0124-4a80-a25d-80e94a8e4ed9</td><td>Emily Wilson</td><td>1995-09-14</td><td>emily.wilson@example.co.uk</td></tr>
</tbody>
</table>
</div><p>Lastly, it’s important to note that the surrogate key is simply a mechanism to identify tuples, so it has no semantics in our domain. In other words, the values taken by the artificial attribute we have generated do not mean anything concerning the tuples or the domain in which they are represented.</p>
<h4 id="heading-secondary-keys">Secondary Keys</h4>
<p>The previous types of keys generally help solve the problem of uniquely identifying tuples. But besides identifying them, it’s important to operate on them and query them efficiently.</p>
<p>To do this, indexes are usually defined on attributes that do not necessarily identify the tables, such as the name or birth date of the previous Person table. By defining an <a target="_blank" href="https://www.freecodecamp.org/news/database-indexing-at-a-glance-bb50809d48bd/"><strong>index</strong></a> on one of these attributes, we can efficiently perform certain operations on the tuples of the table, all based on the values taken by the attributes on which we have defined an index. These attributes are called secondary keys, although we won’t go into detail about what an index is here.</p>
<h4 id="heading-foreign-key">Foreign key</h4>
<p>To finish with the types of keys, the ones we have seen before mainly focus on solving the problem of uniquely identifying tuples, which is the purpose of keys, as well as contributing to the optimization of operations and queries on tables.</p>
<p>But keys also help implement certain elements of conceptual design on the logical design of the DBMS. Specifically, with the type of key we have yet to see, the <strong>foreign key</strong>, we can implement associations between entities at the logical level, which can occur in situations like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751879685769/0d55f4c4-ce27-4aaf-8fc4-59a9717cdb77.png" alt="Entity-relationship diagram where a City is associated with many Person. Image by author. " class="image--center mx-auto" width="998" height="343" loading="lazy"></p>
<p>Here we return to the example where we conceptually model a domain with cities and people, where a person lives in exactly one city, and a city can have any number of people living in it, from 0 to infinity. Given the 1..1 multiplicity on the <strong>City</strong> side, every person must live in some city, but the 0..* multiplicity on the other side means cities may have no inhabitants.</p>
<p>The below diagram represents the conceptual design of our database, capturing certain details of the domain that we later need to transfer to the logical level. On one hand, we transfer the entities themselves to the logical level by creating a table for each entity directly:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>ID</strong></td><td><strong>Name</strong></td><td><strong>Birth</strong></td><td><strong>Email</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Alice Johnson</td><td>1985-07-12</td><td>alice.johnson@example.com</td></tr>
<tr>
<td>2</td><td>Bob Smith</td><td>1990-03-05</td><td>bob.smith@example.org</td></tr>
<tr>
<td>3</td><td>Carol Davis</td><td>1978-11-23</td><td>carol.davis@example.net</td></tr>
<tr>
<td>4</td><td>David Brown</td><td>2001-01-30</td><td>david.brown@example.com</td></tr>
<tr>
<td>5</td><td>Emily Wilson</td><td>1995-09-14</td><td>emily.wilson@example.co.uk</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityID</strong></td><td><strong>Name</strong></td><td><strong>Country</strong></td><td><strong>Population</strong></td><td><strong>Area</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Madrid</td><td>Spain</td><td>3,223,000</td><td>604.3</td></tr>
<tr>
<td>2</td><td>Athens</td><td>Greece</td><td>664,046</td><td>38.96</td></tr>
<tr>
<td>3</td><td>New York</td><td>USA</td><td>8,398,748</td><td>783.8</td></tr>
<tr>
<td>4</td><td>Tokyo</td><td>Japan</td><td>13,929,286</td><td>2,191.1</td></tr>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>2,140,526</td><td>105.4</td></tr>
</tbody>
</table>
</div><p>Given the tables for both entities, we now need to implement at the logical level the association we defined at the conceptual level. This means using a mechanism that allows us to know which city each person lives in or the people who live in a certain city.</p>
<p>If we think about this problem in terms of tables, we’ll see that the only way to do this is to add an additional attribute in one of the two tables so that this attribute takes as values the city where a person lives or the people who live in a certain city.</p>
<p>To understand this correctly, let's first assume that the primary key of the <strong>Person</strong> table is <strong>{PersonID}</strong>, which could be their government ID or an auto-incrementing surrogate key. Also, the primary key of the <strong>City</strong> table is the attribute <strong>{CityID}</strong>. This way, we can uniquely identify the tuples of City and Person using their primary keys, which take unique values for each of their tuples.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>ID</strong></td><td><strong>CityID (FK)</strong></td><td><strong>Name</strong></td><td><strong>Birth</strong></td><td><strong>Email</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>5</td><td>Alice Johnson</td><td>1985-07-12</td><td>alice.johnson@example.com</td></tr>
<tr>
<td>2</td><td>5</td><td>Bob Smith</td><td>1990-03-05</td><td>bob.smith@example.org</td></tr>
<tr>
<td>3</td><td>4</td><td>Carol Davis</td><td>1978-11-23</td><td>carol.davis@example.net</td></tr>
<tr>
<td>4</td><td>2</td><td>David Brown</td><td>2001-01-30</td><td>david.brown@example.com</td></tr>
<tr>
<td>5</td><td>3</td><td>Emily Wilson</td><td>1995-09-14</td><td>emily.wilson@example.co.uk</td></tr>
</tbody>
</table>
</div><p>If we want to know the city where a person lives, we could add an attribute to the <strong>Person</strong> table so that the values it takes belong to the <strong>CityID</strong> attribute as shown above. That is, if the person <strong>"Alice Johnson"</strong> lives in the city <strong>"Paris,"</strong> then in that row, the value of the new attribute <strong>CityID (FK)</strong> we added is 5, which corresponds to the CityID of the city "Paris" in its respective table. Similarly, if the person <strong>"Carol Davis"</strong> lives in the city of <strong>"Tokyo,"</strong> then the new attribute will take the value 4, which corresponds to the CityID of that city in its respective table.</p>
<p>As you can see, the new attribute we added tells us which city the person represented in each row lives in, as it takes the primary key of the City table as its value. So, by knowing the CityID value, we can identify which city it is among all those stored in that table.</p>
<p>This additional attribute we add to represent the association is the foreign key. It mainly serves to implement associations between entities at the conceptual level, through attributes that serve as references or pointers to other tables. This is why it’s sometimes called an association pointer.</p>
<p>Before continuing, it's worth considering what would happen if, instead of placing the foreign key CityID <strong>(FK)</strong> in the Person table, a foreign key <strong>PersonID (FK)</strong> was placed in the City table. If we do this intending to reference all the people who are residents of a certain city, we would encounter a significant problem. That is, if we do this, we must keep in mind that a city can have an arbitrary number of residents, so in the value of its foreign key, we would have to store all the <strong>PersonIDs</strong> of its residents one after another in the same cell. This would result in a repeating group that is prohibited in the relational model.</p>
<p>So to avoid the appearance of this repeating group, we could refine or normalize our diagram, leaving it where we originally placed it in the first place, which is the attribute <strong>CityID (FK)</strong> in the Person table. This would be more complicated than simply changing the table where the foreign key is located.</p>
<p>Now that we understand the basis of what a foreign key is, it's important to note that, for an attribute to truly serve as a foreign key, it must reference an attribute in another table that is a primary key on its own.</p>
<p>In this case, the foreign key is composed of a single attribute, CityID (FK), which references CityID in the City table. If it referenced the Name attribute instead, there could be multiple different cities with the same name. This would mean that if we say a person lives in a certain city and use its name to identify it, we wouldn't be able to know exactly which city they live in if there are multiple cities with the same name.</p>
<p>That's why the foreign key references CityID, which we can guarantee uniquely identifies cities on its own, as it’s the primary key of City.</p>
<h4 id="heading-composite-foreign-key">Composite Foreign key</h4>
<p>Still, we don't always have domains and schemas as simple as these, where primary keys are a single attribute.</p>
<p>For example, we might have a diagram like the following, where there are people who own pools. Each person must own exactly one pool, but it's possible for several people to agree or partner up so that together they can own a pool. This means that each person will own a small percentage of the pool, which in this domain is not relevant. So a pool can be owned by an arbitrary number of people, including none, since there will be pools that aren’t yet owned by anyone.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751883961923/4b86fca3-7a3a-43fe-9fc8-f24a98d405cf.png" alt="Entity-relationship diagram where each Pool belongs to one person, and a person can have multiple pools. Image by author. " class="image--center mx-auto" width="1159" height="385" loading="lazy"></p>
<p>Given the attributes of each entity, we can easily see that the primary key of Person is their <strong>{ID}</strong>, while to uniquely identify a pool, using just <strong>PoolName</strong> or <strong>CityName</strong> is not enough, since there could be multiple pools located in the same city or with the same name.</p>
<p>But if we assume that there can’t be multiple pools with the same name in the same city, we can establish a composite primary key as <strong>{PoolName, CityName}</strong>, where these attributes will uniquely identify each pool. When trying to translate this to the logical level, we first create the tables corresponding to both entities.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>ID</strong></td><td><strong>Name</strong></td><td><strong>Birth</strong></td><td><strong>Email</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Alice Johnson</td><td>1985-07-12</td><td>alice.johnson@example.com</td></tr>
<tr>
<td>2</td><td>Bob Smith</td><td>1990-03-05</td><td>bob.smith@example.org</td></tr>
<tr>
<td>3</td><td>Carol Davis</td><td>1978-11-23</td><td>carol.davis@example.net</td></tr>
<tr>
<td>4</td><td>David Brown</td><td>2001-01-30</td><td>david.brown@example.com</td></tr>
<tr>
<td>5</td><td>Emily Wilson</td><td>1995-09-14</td><td>emily.wilson@example.co.uk</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>PoolName</strong></td><td><strong>CityName</strong></td><td><strong>Length</strong></td><td><strong>Width</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Olympic Stadium Pool</td><td>Los Angeles</td><td>50.0</td><td>25.0</td></tr>
<tr>
<td>Community Center Pool</td><td>Chicago</td><td>25.0</td><td>12.5</td></tr>
<tr>
<td>Lakeside Aquatic Center</td><td>Seattle</td><td>33.3</td><td>15.0</td></tr>
<tr>
<td>Riverside Neighborhood Pool</td><td>Austin</td><td>30.0</td><td>10.0</td></tr>
<tr>
<td>Sunset Community Pool</td><td>Miami</td><td>25.0</td><td>10.0</td></tr>
</tbody>
</table>
</div><p>Later, if we want to model the association between both entities with a foreign key, we first need to consider the cardinality of the association. On one hand, on the <strong>Person</strong> side, we have a cardinality of 0..*, indicating that a pool can belong to many people. On the other side of the association, we have a multiplicity of 1..1, indicating that a person can only have one pool.</p>
<p>With this, we can infer that if we place the foreign key in the <strong>Pool</strong> table, we would have to reference all the people who own each pool, resulting in repetitive groups in cases where there are multiple owners for the same pool (because we’d need to reference each and every owner from the same pool). That is, the pool would have an attribute whose value would be references to all its owners, and since there can be an arbitrary number of them, a repetitive group is formed.</p>
<p>To avoid this problem, whenever we have an association with <strong>cardinality</strong> 1 on one side and * on the other, or equivalents, we need a <strong>foreign key</strong> to model it at the <strong>logical level</strong>. Also, it should generally be placed in the table whose cardinality contains <strong>*</strong> as the <strong>maximum cardinality</strong>*,* indicating an arbitrary amount. Here, by equivalents, we refer to cardinalities like 0..1, which we can treat similarly to 1..1, or 5.., which is equivalent to 0..* because the maximum cardinality is still an arbitrary amount.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>ID</strong></td><td><strong>PoolName (FK)</strong></td><td><strong>CityName (FK)</strong></td><td><strong>Name</strong></td><td><strong>Birth</strong></td><td><strong>Email</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Olympic Stadium Pool</td><td>Los Angeles</td><td>Alice Johnson</td><td>1985-07-12</td><td>alice.johnson@example.com</td></tr>
<tr>
<td>2</td><td>Riverside Neighborhood Pool</td><td>Austin</td><td>Bob Smith</td><td>1990-03-05</td><td>bob.smith@example.org</td></tr>
<tr>
<td>3</td><td>Sunset Community Pool</td><td>Miami</td><td>Carol Davis</td><td>1978-11-23</td><td>carol.davis@example.net</td></tr>
<tr>
<td>4</td><td>Sunset Community Pool</td><td>Miami</td><td>David Brown</td><td>2001-01-30</td><td>david.brown@example.com</td></tr>
<tr>
<td>5</td><td>Olympic Stadium Pool</td><td>Los Angeles</td><td>Emily Wilson</td><td>1995-09-14</td><td>emily.wilson@example.co.uk</td></tr>
</tbody>
</table>
</div><p>As you can see, in this case, the foreign key is placed in the Person table, which is the one with the * in its cardinality on the diagram, since each person can only own one pool. This prevents the foreign key from having to store an arbitrary number of references.</p>
<p>In this specific case, instead of a single attribute, we need to add <strong>PoolName (FK)</strong> and <strong>CityName (FK)</strong> because the primary key of Pool is not a single attribute but two. So the foreign key in Person will be a <strong>composite foreign key</strong> – meaning that instead of one attribute referencing another in a different table, there are two that simultaneously reference two attributes in another table.</p>
<p>For this to be valid, each attribute of the foreign key must reference an attribute of the primary key in the Pool table, so that together PoolName (FK) refers to <strong>PoolName</strong>, and CityName (FK) refers to the <strong>CityName</strong> attribute of Pool. So together they reference the entire primary key of Pool.</p>
<p>Finally, as we’ve just seen, foreign keys are a tool of logical design that we use to implement associations from the conceptual model. That's why in the conceptual model (in the entity-relationship diagram), <strong>we do not write the attributes that form the foreign keys</strong>. This is because at the conceptual level, the associations themselves indicate the relationships between entities. So even though tables have more attributes than we see in the diagram due to foreign keys, <strong>these extra attributes are never written at the conceptual level</strong>.</p>
<p>As for their naming, there are many style guides to follow. Here, we have added an (FK) to the attribute names to make it clear that they are foreign keys or part of one, although they can be named in any other way.</p>
<h3 id="heading-weak-entities">Weak Entities</h3>
<p>Now that we’ve defined how foreign keys allow us to implement associations between entities, we’ll continue by analyzing a case where one of the associated entities can’t be identified on its own with its attributes. Instead, it needs a foreign key that references another entity to be correctly identified – this means that the entity is considered weak in identification.</p>
<h4 id="heading-existence-weakness">Existence weakness</h4>
<p>Before continuing, you should know that there are several types of weaknesses in this context. One is <strong>existence weakness</strong>, which means that an entity called <strong>weak</strong> can’t exist if there isn't another entity called <strong>owner</strong> with which it’s associated.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751893494662/a3f06614-4314-48f5-8a0d-091515af9e1d.png" alt="Entity-relationship diagram where each person is composed of one brain. Image by author. " class="image--center mx-auto" width="309" height="566" loading="lazy"></p>
<p>We can understand this with the previous example, where a person is composed of a brain, and a brain must always be part of a person. So, when an instance of the <strong>Brain</strong> entity is created, meaning a tuple representing a brain is created, a person must also be created to be associated with that person.</p>
<p>In summary, a brain can’t exist without the <strong>Person</strong> entity it’s related to. This leads to an existence weakness where we say the Brain entity is weak and the Person entity is the owner or strong. The composition allows Person to exist without a Brain, even though we prevent it here with cardinality.</p>
<p>Aside from this, when we have an association where all its cardinalities are 1..1, it’s very likely that we can combine those two entities into one, like Person, adding attributes like <strong>Neurons</strong>, instead of having two entities. But this doesn't always have to be done this way, as it depends on how we want to model the domain and the requirements.</p>
<h4 id="heading-identification-weakness">Identification weakness</h4>
<p>In addition to existence weakness, we can have an <strong>identification weakness</strong>. Here, by identification, we mean the mechanism by which each tuple in a table is uniquely distinguished from all others, as we have seen before with keys.</p>
<p>To understand this type of weakness, when it occurs, and how it’s managed, we can look at the following case:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751898026686/2cdc320d-f665-4977-95de-d606a86a9ab2.png" alt="Entity-relationship diagram where Residence is a weak entity that connects City and Person with start and end dates. Image by author. " class="image--center mx-auto" width="1596" height="356" loading="lazy"></p>
<p>Here we have some entities:</p>
<ul>
<li><p><strong>City</strong>, which models cities in the domain</p>
</li>
<li><p><strong>Person</strong>, which does the same for people, and</p>
</li>
<li><p><strong>Residence</strong>, which models a person's stay in a specific city.</p>
</li>
</ul>
<p>This means people can live in a city for a certain time and then move to another. So according to this diagram, they would leave behind an occurrence or tuple of <strong>Residence</strong> with the date they started living in the city and the date they moved to another.</p>
<p>Regarding cardinalities, we can see that a city can be related to many residences, as it may have or have had many inhabitants, while a residence is only related to one person because the residence focuses on recording that a certain person has lived in a certain city. So the 1..1 multiplicities force a residence to link a person with a city, as introducing optionality here would imply that a residence can link a city or person with "nothing," which doesn't make sense.</p>
<p>Meanwhile, on the Residence side, we have 0..* multiplicities with optionality because a person may not live in any city, or conversely, a city may have or have never had any inhabitants, so it may not be related to any occurrence of Residence.</p>
<p>Next, when we translate this diagram to the logical level, we first try to define the primary keys for all the entities or tables. In this case, for City and Person, it's straightforward, as we assume CityID is a unique identifier for each city, and ID is a unique government identifier for each person (tuple).</p>
<p>But when we define the primary key for Residence, we have several options. On one hand, we could choose <strong>{StartDate}</strong> or <strong>{EndDate}</strong> as the primary key, but this isn't feasible because multiple people might start living in the same or different cities on the same start date, end date, or both. So we can't even choose <strong>{StartDate, EndDate}</strong> as the primary key, since, in the worst-case scenario, multiple people might start and stop living in a city at the same time.</p>
<p>This means that the Residence entity needs the other entities it’s associated with to have a primary key and be identifiable. It's important to note that at the logical level, we would have two foreign keys in Residence due to its two associations with City and Person. Specifically, it has a foreign key <strong>CityID (FK)</strong> and another <strong>ID (FK)</strong> that model these associations, respectively.</p>
<p>We can infer this at a glance without "seeing" the logical model because we have associations with cardinalities 1..1 and 0*…* So on the 0.. side, there must be a foreign key to implement this association as we’ve seen before.</p>
<p>Given these foreign keys, we might consider choosing <strong>{CityID (FK)}</strong> or <strong>{ID (FK)}</strong> as primary keys, but this wouldn’t guarantee the identification of all tuples because multiple people can be living in one or several cities at the same time. Also, a city can have multiple residents simultaneously, leading to repeated values in the foreign key attributes for tuples that should be considered distinct.</p>
<p>We also can’t choose <strong>{CityID (FK), ID (FK)}</strong> as a key because a person may have moved to a city multiple times during different periods, even if they lived in other cities in between. This would result in multiple tuples with the same values in both foreign keys but different values in the dates.</p>
<p>Given this situation, the only option left is to consider a key that includes one of the date attributes of Residence and the foreign keys <strong>{CityID (FK)}</strong> or <strong>{ID (FK)}</strong>, since nothing prevents a person from having multiple residences at the same time (where each residence indicates they are living in a city). This is normal because we haven't restricted this situation in any way in the conceptual diagram.</p>
<p>So, since a person can live in multiple cities at once, to identify a Residence tuple, we need to know which person is living in which city, plus at what point in time they are doing so. This we can determine with <strong>StartDate</strong> or <strong>EndDate</strong>. One of the dates is sufficient here, because a person can only live in a city once at the same moment in time, meaning a person can’t start or stop living in the same city multiple times at the same moment.</p>
<p>So to sum up, if we want to uniquely identify the Residence entity, we need to select <strong>{StartDate, CityID (FK), ID (FK)}</strong> as the primary key, although we could also select <strong>{EndDate, CityID (FK), ID (FK)}</strong> as long as we are sure that EndDate always exists. If the end date is not defined until the person leaves the city, we couldn't consider EndDate for identifying Residence.</p>
<p>So we can see here that we can’t identify the entity without using the respective foreign keys. This means the entity is considered weak in identification, as it depends on the two entities City and Person, which in this context are considered the owners of the weak entity. In other words, the owner entities can be identified by themselves, while the weak entity depends on other entities for its identification.</p>
<p>To denote this in the entity-relationship diagram, we can use a <strong>«weak»</strong> role on the sides of the weak entity to indicate that the foreign keys of these associations are needed to identify the <strong>weak entity</strong>.</p>
<p>To correctly understand what weak identification means, we can now consider the same diagram as before. But now, let’s assume that a person can only live in one city at a given moment in time, unlike before when they could live in many cities at once. This restriction can’t be modeled with UML elements, so it's enough to add a textual note in the diagram to reflect the restriction.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751895973100/a7783ee8-ac34-4b92-9bb3-3bb1b425fa7a.png" alt="Entity-relationship diagram where Residence is a weak entity that connects City and Person with start and end dates. Image by author. " class="image--center mx-auto" width="1602" height="342" loading="lazy"></p>
<p>In this case, since a person can only live in one city at a time, we don't need to include the foreign key <strong>CityID (FK)</strong> in the primary key of Residence. If a person is living in a city at a given moment, they can't be living in another, so there won't be more tuples in the table with that person and that start and end date of residence.</p>
<p>Consequently, the primary key of Residence becomes <strong>{StartDate, ID (FK)}</strong>, for example. The only thing that changes besides this primary key is the conceptual diagram itself, where now the only owner entity of Residence is Person because the foreign key to City is no longer strictly necessary for its identification. So even though Residence remains weak, its only owner entity is Person. This is why the role "weak" is only written in the association that gives rise to the foreign key <strong>ID (FK)</strong>, which is indeed in the primary key of Residence (unlike the previous scenario where we placed the role in both associations).</p>
<p>So as you can imagine, with the "weak" roles, we can not only know which entities are weak but also which entities own them. The role is always on the side of the association where the weak entity is found – that is, where the foreign key referencing the owner entity is located, which corresponds with the cardinality * seen before. Then on the other side of the association with the "weak" role, we find the owner entity.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751895191612/68997989-56ee-4a31-bd47-18bb12d9cb60.png" alt="Entity-relationship diagram where Residence connects City and Person with residency dates. Image by author. " class="image--center mx-auto" width="1699" height="409" loading="lazy"></p>
<p>If we want to convert Residence into an entity that is not weak, we need to add enough attributes to identify it without relying on other entities. For example, if we add a surrogate key <strong>ResidenceID</strong> that works through <strong>auto-increment</strong> or <strong>UUID</strong>, then we can automatically identify each tuple of Residence uniquely, so the primary key of <strong>Residence</strong> would become <strong>{ResidenceID}</strong>, and the entity would no longer be weak.</p>
<p>Finally, if we consider the domain we initially proposed and its requirements, we see that Residence is weak in identification, needing both foreign keys to be identified. So in addition to being represented with the "weak" roles in both associations, it’s worth noting the possibility of representing it using an associative entity like the following:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751911354847/f2fb30d9-dcd6-4c0e-8931-40d8ae2f8a76.png" alt="Entity-relationship diagram where Residence connects cities and people, allowing multiple relationships on both sides. Image by author." class="image--center mx-auto" width="1589" height="484" loading="lazy"></p>
<p>We can make the diagram this way in this situation because Residence has Person and City as owner entities. Since it’s linked with the association between both entities and needs both to be identified, it can be denoted as an associative entity.</p>
<p>But an associative entity and a weak entity are completely different concepts, as weakness in identification is a property of entities, while an associative entity is a way to represent entities in UML at a conceptual level.</p>
<p>For example, if Residence had only Person as an owner entity, then it would no longer make sense to represent it as an associative entity at the conceptual level. This is because it’s only a weak entity in identification with respect to one owner entity, Person, not two owner entities that can have an N:M association between them.</p>
<p>In addition to the representation as an associative entity, the cardinalities on both sides of the association must be 0..*, since it was previously stated that a city could have an arbitrary number of residences, where each one had only one person, necessarily. So if we represent Residence as an associative entity, the association between City and Person must have a 0..* on Person. This indicates that a city can be related to an arbitrary number of people through the Residence entity, with the same occurring in the reverse direction.</p>
<h3 id="heading-navigability">Navigability</h3>
<p>In relation to the previous example and the concept of association or foreign key, it's sometimes important to analyze the <strong>navigability</strong> of our entity-relationship diagram before implementing the logical design of the database. This is because efficiency problems, ambiguities, or even the impossibility of performing certain operations or queries may arise.</p>
<p>To begin with, navigability refers to the capacity we have to <strong>“navigate”</strong> on the <strong>entity-relationship diagram</strong> through the associations between entities, or in other words, if we are located on a certain entity, it refers to the ability offered by the associations that affect that entity to navigate these associations and to retrieve information from other entities.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751895191612/68997989-56ee-4a31-bd47-18bb12d9cb60.png" alt="Entity-relationship diagram where Residence connects City and Person with residency dates. Image by author. " class="image--center mx-auto" width="1699" height="409" loading="lazy"></p>
<p>To understand this with an example, we can refer to the last diagram from the previous section where we introduce a surrogate key to Residence. In that diagram, we have an entity Residence with two foreign keys pointing to City and Person. So if we are given a tuple from Residence, we can use its foreign keys to determine which tuple from City or Person is associated with the occurrence of the Residence entity. This allows us to navigate those associations to the corresponding classes.</p>
<p>This is useful, for example, when we query the database to find the person who lived in the city corresponding to that Residence. For this, we can look at the value of the foreign key <strong>ID (FK)</strong>, which corresponds to an identifier of a person recorded in the Person table. This allows us to navigate from the Residence entity to the Person entity, meaning we’ve gotten information from the Person entity starting from Residence.</p>
<p>We can repeat this step multiple times, navigating from entity to entity through the diagram. But the important thing is to know which associations are navigable in a certain direction.</p>
<p>For example, if we are given a person, that tuple doesn't have any foreign keys, so with a tuple representing a person, we can't get information about any other entity in our diagram – not even Residence. If we only look at the values of the Person tuple, we won't know which Residence tuples are associated, because we would need to query and traverse the entire Residence table to find out.</p>
<p>To sum up, the Residence-Person association is not navigable in both directions – we can only go from Residence to Person, but not the other way around. The same applies to City.</p>
<p>Navigability is important, because it's useful to know the direction in which the diagram's associations can be navigated before implementing anything. If our system needs to support a query like obtaining the city where a person currently lives, it might be more efficient to add an association directly from Person to City instead of having to go through all the Residence tuples to resolve the query, which would be more efficient.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751904973527/7d253452-3cdd-4d17-bbfe-cdce7e064f89.png" alt="Entity-relationship diagram where Residence connects City and Person, with an additional direct relationship between them. Image by author. " class="image--center mx-auto" width="1589" height="444" loading="lazy"></p>
<p>Although this association might seem redundant, if we need to focus heavily on optimizing the query we mentioned earlier, it may be worthwhile to "complicate" the diagram in this way so that certain critical queries in our system run faster.</p>
<p>It’s also important to note that a person may not live in any city, which is why the minimum cardinality of the new association on the City side is 0..1. This is because the foreign key resulting from this association may "not exist," as we will see later, representing that a certain person does not live in any city.</p>
<p>Finally, not everything relevant about navigability is related to efficiency, such as when detecting navigation cycles. If several exist, we would need to ensure in the implementation that the DBMS optimizer chooses the shortest one in the corresponding queries.</p>
<p>Navigability also helps us see if certain queries can be resolved, meaning if certain data can be obtained from the system based on some input. And keep in mind that this concept of navigability that we have introduced refers to navigability over the <strong>conceptual diagram</strong> itself, not to the possibility of obtaining information about other entities at the logical level, as we’ll see later.</p>
<h3 id="heading-constraints">Constraints</h3>
<p>Continuing with the elements of the relational model, the only thing left to discuss are constraints. These are conditions imposed on the data to correctly model the domain and meet its requirements. They are a set of rules that must always be followed so that the stored data is correct, consistent, integral, and aligns with the semantics given by the domain.</p>
<p>We can define constraints both at the conceptual and logical levels. On one hand, in the conceptual model, constraints are mainly modeled using the tools provided by UML when creating the entity-relationship diagram.</p>
<p>For example, let’s say that in our domain we have a business rule or condition stating that a city can have a maximum of 500 inhabitants. Then if we model the domain with a diagram similar to those created earlier, we will have an association between person, inhabitant, and city, where we use the cardinality of that association (specifically the maximum cardinality) to represent the constraint of the maximum number of inhabitants.</p>
<p>But not all constraints can be modeled at the conceptual level with UML tools. For example, consider the case where we have a social network with people who can follow other people. We can model this with an entity Person and a recursive relationship where a person can follow an unlimited number of people, including the case where they follow no one.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1751796543335/1224219f-98b8-459b-ae74-e704d06e797a.png" alt="Entity-relationship diagram where Person has a follow relationship with itself. Image by author. " class="image--center mx-auto" width="453" height="409" loading="lazy"></p>
<p>But nothing prevents a person from following themselves, which doesn't make much sense in a social network. So we could leave it as it is if the client doesn't specify otherwise. But if the domain itself or a requirement indicates that a person can’t follow themselves, we will need to add that restriction to the diagram.</p>
<p>Unfortunately, we can’t do this with the tools provided by UML, as there is no mechanism to indicate that this association can’t occur between the same occurrence (tuple) of the <strong>Person</strong> entity.</p>
<p>In this case, we have several options to reflect the restriction in the conceptual design. The first and simplest is to add a textual note on the margin of the diagram where we briefly explain the situation and indicate the rule that makes up the restriction. Notes in UML are standard elements consisting of a box with text where things that can’t be properly modeled with the diagram's own elements are specified.</p>
<p>On the other hand, instead of using a text note, which is less formal and more prone to misinterpretations or confusion, we can use a specific language to represent constraints like <strong>OCL (Object Constraint Language)</strong>, where we define the restriction using the language's own code.</p>
<pre><code class="lang-markdown">context Person
inv noSelfFollow:
<span class="hljs-code">    self.follows-&gt;forAll( p | p &lt;&gt; self )</span>
</code></pre>
<p>Here, we won't go into detail about how constraints are modeled in OCL. The important thing is to know that there are constraints that we can’t directly represent with diagram elements, so they need to be reflected in the conceptual design using notes or specialized language code.</p>
<h3 id="heading-data-integrity">Data Integrity</h3>
<p>As we’ve mentioned, constraints are <strong>validity conditions</strong> imposed on the data. They help ensure that, when stored in our database, they can be checked for correctness, consistency, and integrity, all verified automatically by the DBMS. This is because the constraints themselves are usually implemented at the logical level in the DBMS, which has specific functionalities to check constraints and ensure the correctness and integrity of the data.</p>
<p>So far, we have assumed that the data are stored correctly in their respective tables. We’ve also assumed that they respect the attribute domains, as well as many other details that can affect the validity of what is stored.</p>
<p>So to avoid issues, the database automatically checks the <strong>validity</strong> of the data, which differs from the <strong>correctness</strong> of the data. To understand the difference between these concepts, consider the following example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityID</strong></td><td><strong>Name</strong></td><td><strong>Country</strong></td><td><strong>Temperature <em>(Kelvin)</em></strong></td></tr>
</thead>
<tbody>
<tr>
<td>5</td><td>Paris</td><td>France</td><td>280</td></tr>
<tr>
<td>1</td><td>Madrid</td><td>Spain</td><td>-3</td></tr>
</tbody>
</table>
</div><p>Here we have a Temperature table that stores tuples with the temperatures in a city at different times. As you can guess, the temperature attribute is of type integer, which means it can hold any integer, including negatives. But temperatures can’t be negative if measured in Kelvin, so if we are measuring temperatures in Kelvin here, we must add a domain constraint like <strong>Temperature &gt;= 0</strong> to prevent the Temperature attribute from taking negative values. This is called a domain constraint.</p>
<p><strong>Domain constraints</strong>, as you’ve just seen, are used to define the domains of table attributes, restricting the possible values they can take and ensuring that the stored data is of the appropriate type.</p>
<p>Given this restriction, we can see that the first tuple meets all the constraints, so it could be considered valid data. But with the information we have, we can’t ensure that this data is correct. That is, we have not taken a thermometer and measured the temperature in Paris, so we do not know if that 280 is the actual temperature in Paris or if it’s incorrect data. So even if data meets the constraints, we must ensure that it’s correct.</p>
<p>This is a very complicated task that we won’t go into detail about here. We can implement mechanisms for error detection and correction in data, or we can conduct audits to verify that the data corresponds to reality – that is, the domain. Or third parties can supervise the data, because if the person who took that measurement tells us that the 280 is not what they recorded with the thermometer, then we know that data is incorrect. Otherwise, we would have no way to guarantee its correctness.</p>
<p>On the other hand, in the second tuple, the temperature takes a negative value, so we can conclude that this data is not only incorrect but also invalid. It’s invalid because no Kelvin temperature can be negative, violating the domain constraint imposed earlier. It’s incorrect because if it’s invalid, then that value must necessarily be different from the true temperature of the city.</p>
<p>So now you know what it means for data to be erroneous or incorrect. You also understand domain constraints that can ensure data integrity in terms of data type and possible values that the attribute can take.</p>
<p>But data integrity goes beyond simply checking that data is in the correct format and within an attribute's domain. For example, data must be <strong>reliable and accurate</strong>, which we verify with its correctness. It must also be <strong>consistent</strong>, meaning there can’t be duplicate tuples with information that leads to contradictions as seen earlier. It must also have other high-level characteristics like availability, durability, data timeliness, security, and so on which we won’t delve into because they aren’t essential here.</p>
<h3 id="heading-integrity-constraints">Integrity Constraints</h3>
<p>In addition to the previous characteristics, there is another one that’s essential for maintaining data integrity: completeness. In this context, completeness can have several meanings, with the simplest being that all data points are present in the database as tuples. This means all the "individuals" of the domain are represented in the database.</p>
<p>For instance, if we are storing a domain with 10 people and only see 9 tuples in a table like Person, we know that the data is not complete because the entire domain is not represented by the 9 tuples. On the other hand, completeness also means that each data point must necessarily have a value for each attribute of the table that defines it.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityID</strong></td><td><strong>Name</strong></td><td><strong>Country</strong></td><td><strong>Population</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Madrid</td><td>Spain</td><td>3,223,000</td></tr>
<tr>
<td>2</td><td>Athens</td><td><strong>NULL</strong></td><td>664,046</td></tr>
<tr>
<td>3</td><td>New York</td><td>USA</td><td>8,398,748</td></tr>
<tr>
<td>4</td><td>Tokyo</td><td>Japan</td><td>13,929,286</td></tr>
<tr>
<td>5</td><td>Paris</td><td>France</td><td><strong>NULL</strong></td></tr>
</tbody>
</table>
</div><p>For example, if we have a domain with cities, and in our database we include a <strong>City</strong> table with these attributes, then each city (data point) we represent with a tuple must have a value for each of these attributes. This means that for the data to be complete, no cell in the table can be empty.</p>
<p>In the table above, you can see that the cities named <strong>"Athens"</strong> and <strong>"Paris"</strong> prevent the data from being complete, as one does not have a value in the <strong>Country</strong> attribute and the other in Population, respectively. Instead of leaving the corresponding cells empty, the special value <strong>NULL</strong> is stored in them to represent that they contain nothing.</p>
<p>To ensure the completeness property of the stored data, NULL values should be avoided in the tables. But we will later see that by default, DBMSs do not usually enforce the restriction that table values can’t be NULL. In other words, when we create a table by default, the values of the tuples can be NULL unless we define otherwise through a restriction.</p>
<p>We typically define this restriction at the attribute level, where we specify that the values in the column corresponding to that attribute can’t be NULL. So all tuples we save in the table must have a value other than NULL for that attribute.</p>
<p>This affects the attribute's domain, since by default, the special value NULL is included in the set of all values an attribute can take. But we can exclude this value from the set using a restriction.</p>
<p>In light of all this, and after introducing the concept of NULL, we can define integrity as a property that ensures that throughout its entire lifecycle, the stored data is valid, correct, consistent, complete, and reliable.</p>
<p>To ensure that all these characteristics are met (except for the last one, which is at a higher level), we use special types of constraints in the database, known as integrity constraints. In other words, we can categorize database constraints based on their purpose.</p>
<p>Some constraints dedicated to modeling business domain requirements and rules, while others are integrity constraints specifically aimed at enforcing the aforementioned integrity characteristics (but some of them may also indirectly model part of the business rules).</p>
<p>These last constraints are validity conditions automatically checked by the DBMS every time an operation is performed on the entity (table) or entities affected by these constraints, all with the goal of ensuring data integrity at all times.</p>
<p>These validity conditions, as we’ve seen, must be met for all stored tuples, ensuring that none of them can have an empty cell or a disallowed value. In other words, conditions can be defined at the attribute (column) level, although the tuples stored must adhere to these constraints. This is why they are checked for all of them. So when all the tuples stored in a table meet all the defined integrity constraints, the instance of that table is said to be <strong>legal</strong>.</p>
<p>Integrity constraints, depending on their logical purpose, can be classified into several types:</p>
<p><strong>First, we have domain constraints.</strong> These are the ones we just discussed, and they mainly serve to define the data type of the attributes and their domain.</p>
<p>On one hand, implicit domain constraints include those that define the data type of the attributes, as this is something we must do when creating a table, not something we add later to limit the attribute's domain.</p>
<p>On the other hand, there are explicit domain constraints, which we add in addition to the data type definition to limit the values that attributes can take, such as preventing them from containing the special value NULL, or preventing an attribute that stores temperatures in Kelvin from taking negative values, as we have seen. We can also consider it implicit that the DBMS allows cells to take NULL values, which we can prevent by setting an explicit constraint.</p>
<p><strong>Next, we have identification constraints.</strong> Regarding the identification of tuples, we previously saw that a primary key is chosen for each table so that its attributes can uniquely identify all the tuples stored in it. The explicit definition of a primary key is an integrity constraint that we define on the table.</p>
<p>But by doing this, the DBMS internally applies several sub-integrity constraints, one of which ensures that the combinations of values taken by the primary key attributes are all different (meaning unique). This is what characterizes a key. Also, none of the attributes can take NULL as a value, because if they could, there would be multiple tuples with the same value for the primary key.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>ID</strong></td><td><strong>Name</strong></td><td><strong>Birth</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Alice Johnson</td><td>1985-07-12</td></tr>
<tr>
<td><strong>NULL</strong></td><td>Bob Smith</td><td>1990-03-05</td></tr>
<tr>
<td>3</td><td>Carol Davis</td><td>1978-11-23</td></tr>
<tr>
<td>4</td><td>David Brown</td><td>2001-01-30</td></tr>
<tr>
<td><strong>NULL</strong></td><td>Emily Wilson</td><td>1995-09-14</td></tr>
</tbody>
</table>
</div><p>For example, if our primary key is a single attribute <strong>{ID}</strong>, then it can’t take NULL as a value, because in that case, we could have multiple tuples with NULL in that attribute as seen above, preventing them from being uniquely identified.</p>
<p><strong>Lastly, we have referential constraints.</strong> Related to the previous constraints are referential integrity constraints, which ensure that the relationships between tables are consistent at all times. These constraints are implicit, meaning the DBMS automatically ensures that they’re fulfilled. Still, we must explicitly define which attributes are foreign keys for it to do so.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752060524956/e7efb90c-04f2-4581-b12d-cb443a028f25.png" alt="Entity-relationship diagram where Pool is a weak entity dependent on City. Image by author. " class="image--center mx-auto" width="1067" height="340" loading="lazy"></p>
<p>Here, by consistent, we’re not referring to the same concept as data consistency. Rather, we mean that a foreign key must reference a valid tuple in the table it points to.</p>
<p>For example, if we have a weak entity Pool whose logical table has a foreign key attribute like <strong>CityID (FK)</strong>, then whenever this attribute references a city, it must contain a valid CityID value. This means it must exist in the City table. If the value doesn't exist, then it wouldn't be referencing any city.</p>
<p>Also, note that the foreign key attribute itself can be NULL by default unless we specify otherwise, because the foreign key constraint doesn't behave like the primary key constraint, which implicitly prevents NULL values. Instead, the foreign key constraint is solely focused on ensuring consistency in references, not on preventing NULL values.</p>
<p>To understand this, we need to look at the 1..1 multiplicity on the City side, which requires all pools to belong to exactly one city, ensuring no pool is "loose" or outside a city. This means all pools must have a value in their foreign key <strong>CityID (FK)</strong>, as they must belong to one and only one city.</p>
<p>For this restriction (which we've conceptually modeled with a minimum cardinality) to be translated to the logical level, we need to explicitly indicate a <strong>domain integrity constraint</strong> on the <strong>CityID (FK)</strong> attribute so it can’t contain NULL values. This means it must always refer to a city. This, in turn, allows the Pool entity to be identified by the pool's name and the city where it's located, as the name can be repeated in several tuples/pools. But the combination of the name and city where they are located is assumed to never repeat in our domain. In other words, in the same city, there are no multiple pools with the same name.</p>
<p>Assuming this, if in our database we have a series of tuples in both tables and we want to delete a city from the record, then we need to check if there is any pool referencing that city. This would prevent the city record from being deleted to maintain integrity and ensure that the respective foreign key of the pool continues to reference an existing city.</p>
<p>To resolve this situation, there are many policies that we will see later, although the most common is to prevent the deletion operation from being executed or to also delete the pool record that references the city we want to delete. This could cause more recursive deletions if there are foreign keys pointing to Pool.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752061005445/a3dab918-7ccc-42b8-b0da-2956bebe1e79.png" alt="Entity-relationship diagram where a City can have none or one Pool, and a pool can belong to none or one city. Image by author. " class="image--center mx-auto" width="1074" height="359" loading="lazy"></p>
<p>On the other hand, if the minimum cardinality on the <strong>City</strong> side is 0, this means that at the logical level, the foreign key of Pool may not exist – meaning the pool might not be in any city. So its foreign key can take the value NULL because it's the only simple way to implement that the foreign key itself "does not exist."</p>
<p>If we do this, we won't have to define the explicit constraint that the foreign key attribute is non-null, and when deleting a city record, we can set the deletion policy so that the foreign key in Pool is set to NULL.</p>
<p>As for the weakness in identifying <strong>Pool</strong>, it disappears here because it can't use its foreign key for identification since it can take the value NULL and the pool name can be repeated. Because of this, we decide to add a surrogate key <strong>PoolID</strong> to identify the Pool entity.</p>
<p>Finally, nothing prevents a foreign key from modeling a recursive relationship, meaning the DBMS implicitly allows it by default. So if we want to avoid situations where a tuple references itself, we must add explicit constraints, which we can categorize as referential integrity.</p>
<h2 id="heading-chapter-6-relational-schema-diagram">Chapter 6: Relational Schema Diagram</h2>
<p>After introducing the relational model at the conceptual level, we must remember that this is the first level of database design. Now, based on the entity-relationship diagram, we need to determine the tables that will make up the database, as well as the keys they will have to identify and reference each other. We also need to define the constraints that ensure the validity and integrity of the data.</p>
<p>So even though we’ve already introduced certain concepts of logical design, here we’ll formalize the logical design itself through relational schema diagrams, sometimes called relational diagrams for simplicity.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752067358857/9f4bba9e-330a-44d3-b162-32681c5e5196.png" alt="Relational schema diagram where Pool references City through a foreign key. Image by author. " class="image--center mx-auto" width="1371" height="437" loading="lazy"></p>
<p>As you can see, here we have a relational diagram representing the logical design associated with the last entity-relationship diagram from the previous section.</p>
<p>First, instead of entities, we have tables here, each with a series of attributes. If any attribute is used in a primary key, it’s underlined like PoolID or CityID, with all other attributes being "normal" table attributes. Also, foreign keys are represented directly with arrows. In this case, CityFK is a foreign key that references the CityID attribute of the City table because it’s a primary key, which is why it's denoted with an arrow pointing from the foreign key attribute to the corresponding attribute in the other table.</p>
<p>Regarding the foreign key, keep in mind that an attribute can only point to one other attribute – meaning CityFK can only have one arrow pointing to one attribute, not several, as the foreign key references a single attribute in another table. If we were asked to convert this relational diagram into an entity-relationship diagram, the foreign key itself would determine the cardinalities of the association (at least the maximum cardinalities, since, for that foreign key to make sense, at the conceptual level, it would translate to a pool being in only one city at most, while a city can have an arbitrary number of pools).</p>
<p>These types of diagrams aren’t standard like UML. They only need to meet the characteristics mentioned earlier. That's why, in many cases, tables are represented with squares similar to UML entities instead of being shown in textual format with Datalog.</p>
<p>But unlike UML diagrams, there are very few implicit restrictions here. Most restrictions need to be added with notes in the margins. For example, to indicate that an attribute can’t have a NULL value, we can’t do it with diagram elements – instead, it must be represented by other means, such as a note or a piece of code in <strong>OCL</strong>.</p>
<h3 id="heading-1-1-association">1-1 association</h3>
<p>Given the nature of relational diagrams, we can infer that entities are directly transferred to the logical model with tables, where each entity corresponds to a table. But in addition to the tables, we have to implement the associations between entities at the logical level.</p>
<p>To do this, we start with the simplest case, which is an association where the maximum cardinality on both sides is 1, as in the example we saw earlier where we had an entity Person composed of an entity Brain, whose translation to a relational diagram would be as follows.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752069584062/a369d85c-5287-48e8-8822-18f503c0ae9e.png" alt="Relational schema diagram where Person and Brain reference each other through foreign keys. Image by author. " class="image--center mx-auto" width="1423" height="582" loading="lazy"></p>
<p>As you can see, both entities are represented with tables, where the attributes of their primary keys are underlined. Also, even though they don't appear in the conceptual diagram, we need to reflect the existence of foreign key attributes used to implement the association itself.</p>
<p>So we’ve added attributes with names that best indicate that they are foreign keys. In this case, the name ends with FK, although you can use any name you like. So for a brain to be associated with a person, its corresponding foreign key refers to the primary key of the table that stores people. Since the other direction of the association is symmetrical, we do the same with the foreign key of Person (which refers to the primary key of Brain so that a person can be associated with their corresponding brain). We do this with foreign keys for simplicity and because it's the only way to determine which brain each person has and to whom each brain belongs.</p>
<p>Because of the 1-1 association, you typically shouldn’t leave this type of association due to the overhead caused by using multiple foreign keys referencing in both directions, and the redundancy at the conceptual level. If each person has one brain and only one, and vice versa, it's likely that both can be "merged" and modeled as a single concept, moving all the attributes that characterize Brain to the Person entity, for example. But there are other ways to refine the schema, or there are times when the domain or requirements force us to keep this type of relationship, in which case it would be perfectly valid.</p>
<h3 id="heading-1-m-association">1-M association</h3>
<p>Another type of association we need to translate to the logical level is called 1-M (or 1-N), which refers to associations where the maximum cardinalities on both sides are 1 and * respectively, where M means an arbitrary amount.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752069775099/caf1b28f-a301-451a-942f-a6a381f10ca5.png" alt="Entity-relationship diagram where each House belongs to a single Person, who can have multiple houses. Image by author. " class="image--center mx-auto" width="956" height="322" loading="lazy"></p>
<p>For example, here we have a 1-M relationship between the entities House and Person, where a house must belong to a person, and a person can have an arbitrary number of houses, including none. At the logical level, we can represent this as:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752074660667/ba64c7d8-7315-4f00-b3ff-0915af14d5d4.png" alt="Relational schema diagram where House references Person through a foreign key. Image by author. " class="image--center mx-auto" width="1446" height="394" loading="lazy"></p>
<p>Just like before, we implement both entities with tables, and the 1-M association between them with a foreign key in the entity on the side where the maximum cardinality is *. Specifically, to avoid repetitive groups, we place the foreign key in house, since a house can only have one person as its owner. This means it won't be necessary to store an arbitrary number of references in the attribute of its foreign key – one is enough.</p>
<p>And as always, the foreign key refers to the primary key of Person, so that it can reference a value of an attribute that can uniquely identify a person, and thus determine the owner of a house.</p>
<h3 id="heading-minimum-cardinality-issues">Minimum cardinality issues</h3>
<p>Regarding the previous entity-relationship diagram, we can see that the 1..1 side indicates that at a minimum, a house must always be associated with a person who will be its owner. This means that a house must always have an owner. But this is not realistic, as when a house is built, it may be without an owner for some time, causing the cardinality on that side of the association to become 0..1.</p>
<p>In turn, the minimum cardinality of 0 means that a house may not have an owner – so its foreign key should not exist while the house has no owner. To model this, attributes, including foreign keys, are allowed to take NULL as a value by default (as we’ve seen before). This way, to represent that the foreign key does not point anywhere, we simply choose not to restrict the possibility of it taking this NULL value. So when a house has no owner, its foreign key attribute will be NULL until it references a person – that is, a tuple in the Person table.</p>
<p>This situation, where a foreign key is allowed to take the NULL value, is not explicitly indicated in the relational diagram. Instead, it’s indicated when the opposite situation occurs – where if the foreign key can’t be NULL, we need to add a note clearly indicating this (as is the case in the original entity-relationship diagram we just saw).</p>
<p>On the other hand, the association in the diagram has a multiplicity of 0..* on the House side, indicating that a person doesn’t have to own any house. But if we had a minimum cardinality greater than 0, then this restriction would need to be defined with a note in the relational diagram, as well as with specific SQL tools (since there are no standard elements to model this type of requirement caused by minimum cardinalities in such a situation).</p>
<h3 id="heading-n-m-association">N-M association</h3>
<p>To conclude with the types of associations according to their cardinality, the only one left to translate is N-M. In this case, N and M denote arbitrary quantities, meaning associations whose maximum cardinalities are both * at the same time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752077406305/f54614f5-082a-4541-bc82-7146ffc640db.png" alt="Entity-relationship diagram where House and Person have a many-to-many relationship. Image by author. " class="image--center mx-auto" width="1180" height="341" loading="lazy"></p>
<p>As an example, we could have a domain where a person can own many houses, and a house can be owned by many people at the same time. To model this situation at the conceptual level, the first thing we might think of is to create a diagram like this, where we only put an association with cardinality 0..* on both sides.</p>
<p>Conceptually this would be consistent, but logically it can’t be translated in any way. That is, if we have an association with a maximum cardinality of * on both sides and try to implement it logically using foreign keys as we’ve done so far, we’ll find that even if we put a foreign key in both entities referencing the entity on the other side of the association, the problem of the repeating group will always appear in both entities, regardless of what else we do.</p>
<p>To understand this, we can look at it conceptually. If a person has an indeterminate number of houses and we put a foreign key in Person referencing House, then that foreign key would need to contain references to each of the possible houses the person might have. Since it's not a fixed number, a repetitive group appears in the foreign key.</p>
<p>The same happens in reverse: if a house can have an arbitrary number of owners, then including a foreign key in House referencing Person would cause a repetitive group in the foreign key. So this type of association does not have a direct implementation at the logical level.</p>
<p>But in reality, these situations usually don't occur this way. Instead, it's common for there to be an intermediate class in the association that allows for its implementation at the logical level, as in the following example:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752070941510/823b8d0c-c00f-4115-92bb-59b31f8fc1a1.png" alt="Entity-relationship diagram where Property connects houses and people with sale dates and prices. Image by author. " class="image--center mx-auto" width="1666" height="356" loading="lazy"></p>
<p>Here, we have a situation similar to the previous one, where a person can own an arbitrary number of houses, and a house can be owned by an arbitrary number of people. The difference here is that we assume one of the domain requirements is to record when a person buys and sells a house, as well as the price at which it was bought. We don’t need the the selling price because it will be the purchase price for another occurrence of Property.</p>
<p>For this, we use an intermediate Property entity that stores this data, where we must keep in mind that SellDate should not "exist" until the house is actually sold, if it’s sold at all. So to translate this to the logical level, the simplest approach is to allow SellDate to be NULL until the house is sold.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752071179227/4dd3de56-2a14-4cbc-ab56-944445b7de91.png" alt="Relational schema diagram where Property references House and Person through foreign keys. Image by author. " class="image--center mx-auto" width="1329" height="463" loading="lazy"></p>
<p>As we can see, this situation can now be translated into a relational diagram, meaning at the logical level. This is because all entities can be represented as tables. And since the associations are of the 1-M type, we already know how to implement them using foreign keys, specifically in the Property entity referencing the primary keys of the other two entities, respectively.</p>
<p>This doesn't mean that whenever we have an N-M relationship, we need to introduce an intermediate entity to implement it. Sometimes we need an intermediate class to store information, as in this case, and in other situations, we might need to refine the schema because the N-M relationship doesn't best represent the domain.</p>
<p>But if we really need to implement an N-M relationship and we’re sure that this relationship is conceptually correct, we can always add an artificial intermediate entity that has no attributes other than the foreign keys of both associations (with both being the primary key), thus making it a weak entity in identification.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752070430749/a6f7f0cc-7fcb-4fce-ac0f-6d41fc1e7610.png" alt="Entity-relationship diagram where Property is a weak entity that connects House and Person with sales data. Image by author. " class="image--center mx-auto" width="1666" height="309" loading="lazy"></p>
<p>For example, considering the situation where we do need to store information in an intermediate class, we previously saw that Property had its own primary key, <strong>PropertyID</strong>, probably derived from a surrogate key. But if there is no surrogate key, we must try to identify the tuples of Property through their attributes. In this case, this isn’t possible given their semantics – meaning the significance of what they store – as there could be multiple tuples with the same dates, prices, and so on.</p>
<p>So, knowing that two foreign keys will appear in Property referencing House and <strong>Person</strong> when translated to the logical level, we can use them to define the primary key of Property using <strong>BuyDate</strong> and the foreign key attributes themselves.</p>
<p>We do this because if we only make the primary key consist of the foreign keys, then Property can’t be uniquely identified if a person buys and sells the same house during multiple different time periods. So we add BuyDate to the primary key to also distinguish by purchase date, because <strong>SellDate</strong> can be <strong>NULL</strong> (which violates the fundamental integrity constraint of primary keys that none of their attributes can be NULL). With this, the <strong>Property</strong> entity becomes weak in identification, which is why we’ve added <strong>«weak»</strong> to both sides, indicating that we need both foreign keys for identification.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752070636272/b40fe320-933b-46c3-98b0-7d0838c59de1.png" alt="Entity-relationship diagram where Property links houses and people with purchase and sale information. Image by author. " class="image--center mx-auto" width="1658" height="493" loading="lazy"></p>
<p>Similarly, in this case, since the weakness in identification affects the entities on both sides (meaning we need the foreign keys referencing the entities on both sides of Property), it can be represented conceptually with an associative entity linked to the M-N association between House and Person. This is still equivalent to the previous diagram, with the only difference being that the intermediate class is represented differently.</p>
<p>Also, it’s important to note that if Property had a surrogate key and did not need foreign keys for its identification, this representation using an associative entity would not be valid. Ultimately, the associative entity is only valid to use in this context when the intermediate entity <strong>depends</strong> on the two linked entities for its identification, with these being its owning entities.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752071302075/d712f40f-1b86-4a5c-bc84-0f5f33851215.png" alt="Relational schema diagram where Property references House and Person through foreign keys. Image by author. " class="image--center mx-auto" width="1110" height="452" loading="lazy"></p>
<p>Regarding the logical-level translation of this last case, we. doit in the same way – the difference being that we no longer have the PropertyID attribute in Property. Also, its primary key is now <strong>{BuyDate, HouseFK, PersonFK}</strong>, so we underline all those attributes.</p>
<p>As a general rule, when a foreign key is underlined in a relational diagram, it indicates that the conceptual-level entity corresponding to the table is weak in identification. This lets us know how many entities it depends on – that is, its owning entities.</p>
<h3 id="heading-is-a-hierarchy">IS-A Hierarchy</h3>
<p>After seeing how entities and associations from the relational model are translated to the logical level, let’s now understand how the special relationships of generalization and specialization among the entities themselves are translated.</p>
<p>To do this, we’ll start with an example of an IS-A hierarchy. This basically means that one or more entities, like CityPool, are a specialization of another more general entity, Pool. This is very similar to what happens in object-oriented programming with inheritance.</p>
<p>The inheritance hierarchy is called IS-A because if CityPool inherits from Pool, then it’s more specific than Pool. This means that every city pool is a pool, but it has specific attributes that characterize city pools, such as their maximum user capacity or the ticket price.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752081799527/5f6d4146-0884-4ba5-8125-3ae064748ff6.png" alt="Entity-relationship diagram with inheritance where CityPool and OlympicPool are subclasses of Pool. Image by author. " class="image--center mx-auto" width="770" height="563" loading="lazy"></p>
<p>Before seeing how they are translated to the logical level, it's important to know that IS-A hierarchies have a series of specialization constraints that determine the "relationship" the parent entity (Pool here, sometimes called superclass) has with the specific entities. In other words, if we consider that entities are actually sets containing all their occurrences (tuples) (which we’ll call individuals here to keep it a more "general" concept), away from the details of the conceptual and logical model, then we can establish constraints like <strong>completeness</strong> or <strong>disjunction</strong> of a hierarchy.</p>
<p>To understand completeness using this example, we can first have hierarchies that are complete, where all individuals of the entity Pool must necessarily belong to the sets of individuals of one of the specific entities that inherit from the superclass Pool.</p>
<p>In this case, the superclass <strong>Pool</strong> is an entity that contains all existing pools. So some of them might be city pools, belonging to the set of individuals formed by the inheriting entity <strong>CityPool</strong>. Others might be Olympic pools, which belong to the set of individuals of <strong>OlympicPool</strong>.</p>
<p>In our model, we have only specified these two types of pools, while in reality, there are many other types of pools. In this hierarchy, they’d be represented by individuals in the set generated by Pool, as they don’t have any inheriting class to belong to. So in this case, our hierarchy would not be complete, but <strong>partial</strong>, since there are pools that do not belong to any inheriting entity.</p>
<p>On the other hand, <strong>disjunction</strong> refers to the possibility of individuals belonging to more than one inheriting entity at the same time. For example, in our case, a pool is either a city pool or an Olympic pool, or it’s neither of those types – so we will never find a pool that is both a city and an Olympic pool at the same time.</p>
<p>If we consider the sets of individuals of the inheriting entities, the hierarchy is considered <strong>disjoint</strong> when those sets are disjoint, as in this case where pools are either one type or the other, but not both at the same time. Conversely, in cases where the latter occurs, the hierarchy is called overlapping.</p>
<h4 id="heading-1-table">1 table</h4>
<p>Knowing now that the hierarchy in our example is incomplete (called partial) and disjoint, we need to implement what’s shown in the entity-relationship diagram at the logical level.</p>
<p>We have several options for this. One option is to implement the entire IS-A hierarchy with a single table, Pool, that gathers all the attributes of the tables in the hierarchy.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752083879943/097a29cd-6b8d-41ca-ad49-6bed9562026a.png" alt="Image by author. Relational schema where Pool includes attributes for capacity, price, and competition features." class="image--center mx-auto" width="1349" height="69" loading="lazy"></p>
<p>As you can see, in this option we implement a table that contains all the attributes of the three tables, where PoolID functions as the primary key of the entire Pool table, since in the conceptual design specific identifiers aren’t usually assigned to inheriting entities unless required. This is why PoolID appears underlined. As for the rest, they work the same as if they were in their respective entities.</p>
<p>On one hand, this option has the advantage of using only one table for the entire hierarchy, which makes it easier to understand and maintain. It also avoids the possible redundancy of storing the same information in multiple tables.</p>
<p>But on the other hand, it presents significant problems. First, we have no simple way to distinguish a pool from a city pool or an Olympic pool, meaning the only way to know the specific type of pool that a tuple in the Pool table represents is to have some attributes be NULL.</p>
<p>For example, if a tuple represents a pool from the Pool entity, then all the attributes of CityPool and OlympicPool must be NULL so that the corresponding tuple only takes values in the attributes of the Pool entity. This lets us determine that the tuple represents an "individual" of the set of occurrences of the Pool entity.</p>
<p>The same thing happens when we try to distinguish city pools, where all the attributes of OlympicPool must be NULL, since CityPool inherits all the attributes of the Pool entity. So all those attributes plus those specific to CityPool will have values, while those of OlympicPool will be NULL to indicate that the pool is a city pool. This also happens when we want to know if a tuple represents an Olympic pool, where the attributes of CityPool will be NULL.</p>
<p>So if we implement the IS-A hierarchy with a single table, we will have the problem of distinguishing the types of pools – that is, knowing if a tuple represents an occurrence of the superclass entity or one of the inheriting entities. This could lead to a potentially large number of NULL values occupying unnecessary space in the table, even though working with such a table might be easy to understand.</p>
<p>Also, we can also consider the ease with which the schema can be extended or modified as an advantage. This is because if a foreign key is later added in our domain in any of the 3 tables of the hierarchy referencing another entity, it would simply be necessary to add a foreign key attribute to the Pool table. Similarly, if an external foreign key points to any of the entities in the hierarchy, it would only need to reference PoolID.</p>
<h4 id="heading-2-tables">2 tables</h4>
<p>To address the previous problem of distinction, another option we have for implementing the hierarchy is to use two tables, or as many as there are inheriting entities. The basis of this is that all inheriting entities have the same attributes as the superclass they inherit from, plus a series of specific attributes that characterize them.</p>
<p>So to logically distinguish the inheriting entities, we can implement specific tables for each one, where they have the same attributes as the superclass plus their own.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752084244540/f47a6034-0fa1-43e4-8040-ad5177e1976d.png" alt="Relational schema where CityPool and OlympicPool inherit common attributes and add specific fields. Image by author. " class="image--center mx-auto" width="1428" height="172" loading="lazy"></p>
<p>As you can see, in this option we implement the CityPool and OlympicPool tables, which are responsible for storing tuples that represent city pools and Olympic pools, respectively. Since each contains the same attributes as the subclass, even though they aren’t explicitly copied in the inheriting entities in the conceptual diagram, both have the same primary key, PoolID.</p>
<p>This implementation offers various advantages: first, we eliminate unnecessary NULL values used to distinguish pool types, at least those modeled through the inheriting entities. Also, the schema remains simple, being easily understandable and maintainable due to the semantics of each table.</p>
<p>But there is also a distinction problem here, as our hierarchy is not complete. This means that there will be pools that are neither city nor Olympic, so they can’t be represented with tuples from CityPool or OlympicPool. In other words, this option doesn’t work for representing incomplete hierarchies, as the only way we could represent a pool that is neither of these types would be to insert an identical tuple in both CityPool and OlympicPool with all attributes not belonging to the superclass set to NULL. But this would be very counterproductive in terms of memory usage, and would also be complicated to manage.</p>
<p>On the other hand, even if the hierarchy were complete, a possible disadvantage to consider is the repetition of the superclass attributes in all tables, where this repetition wastes space in our database.</p>
<p>But even if we have extra space and can afford to repeat all those attributes, if we want to gather all the data about all the pools <em>(or individuals)</em> that exist, we would need to collect the data present in all the tables, which may not be entirely efficient.</p>
<p>Lastly, if our conceptual model has a foreign key referencing the superclass entity Pool, we need to consider that the primary key of Pool has now been transferred to the two tables. This means that foreign key would have to reference both tables at once, which isn’t possible. So instead of referencing an attribute of one table, it would have to reference PoolID from both CityPool and OlympicPool at the same time. This would complicate or even make the implementation impossible at the logical level.</p>
<p>Regarding foreign keys, this option would indeed allow us to easily implement a foreign key in one of the entities, CityPool or OlympicPool, that references another entity (or even foreign keys that reference these entities in a straightforward manner).</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752084458598/f27a5174-8f88-4ed1-8459-1dd1cb15c8dc.png" alt="Relational schema where OlympicPool inherits from Pool, adding competition and certification attributes. Image by author. " class="image--center mx-auto" width="1327" height="231" loading="lazy"></p>
<p>But, if we insist on using two tables to implement the hierarchy, we could refine the logical schema to solve the problem of a foreign key referencing the superclass in this way.</p>
<p>As you can see above, we have two tables where one is exclusively dedicated to storing tuples that contain the attributes characterizing an Olympic pool. The other entity encompasses all pools, including city pools and Olympic pools. This is because an Olympic pool also inherits the attributes of the superclass, so to represent it in this schema, we create two tuples: one in Pool that stores the values of the superclass attributes, leaving the rest as NULL, and another tuple in OlympicPool that stores the remaining attributes, with its foreign key (which is also the primary key), referencing the corresponding tuple in Pool with the superclass attribute values.</p>
<p>The main advantage of this option is that it solves the problem of having an external foreign key referencing Pool – as in this case, it would simply need to point to the primary key {PoolID} of Pool, instead of several attributes at once as it did before.</p>
<p>But this leaves us with a significantly more complex schema to understand and work with, as the way to store a city pool is entirely different from storing an Olympic pool. This complicates certain operations like inserting an Olympic pool, where we’d need to create two tuples in Pool and OlympicPool so that the primary/foreign key of OlympicPool points to the tuple created in Pool. It also complicates counting the pools that are neither Olympic nor city pools in the system, where all those tuples in Pool with NULL in the attributes characterizing city pools must be found.</p>
<p>Finally, although we see that the primary key of OlympicPool is also foreign in this implementation, this doesn’t imply that conceptually it’s a weak entity in identification. There are many ways to implement the hierarchy, and this is not necessarily the one that must be carried out.</p>
<h4 id="heading-3-tables">3 tables</h4>
<p>So, if we have an incomplete hierarchy and really want to make sure that the implementation lets us distinguish between the different types of pools and identify those pools that don’t belong to any inheriting entity, we can use three tables – one for each entity, respectively.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752084637220/69491535-2a0c-4080-bf09-10967addced1.png" alt="Relational schema where CityPool and OlympicPool inherit from Pool, adding specific attributes. Image by author. " class="image--center mx-auto" width="1434" height="197" loading="lazy"></p>
<p>The peculiarity of this schema is that since all pools contain the attributes of the superclass Pool, whenever there is a pool in our database, it will be represented by a tuple in the Pool table that contains only the values of the superclass attributes. And, if a pool is of a specific type, it will be represented not only by the Pool tuple but also by a tuple in one of the tables reserved for the inheriting entities, where each has a foreign key pointing to the primary key {PoolID} of Pool.</p>
<p>For example, a city pool can be represented by a tuple in CityPool (which only has the specific attributes that characterize it as a city pool) plus a foreign key pointing to a specific tuple in Pool that holds the values of the other inherited attributes.</p>
<p>The advantage of this schema is that it minimizes wasted space from duplicated information or the appearance of NULL values (as the only thing being "duplicated" here is the PoolID attribute as foreign keys in the inheriting entities). It’s also easy to understand because each entity is represented by a specific table at the logical level.</p>
<p>Also, the schema is easy to modify in cases where we need to add foreign keys to the entities, where it would simply require adding an additional foreign key attribute or implementing external foreign keys pointing to the entities themselves, which we can do by referencing their own primary and foreign keys {PoolID}.</p>
<p>If we add a new type of pool to the domain later, it’s easy to add a table very similar to the ones we already have. This is unlike the previous options we saw where adding a new type of pool would be more costly because of the elements that need modification. Also, having three tables makes it easy to model the constraints related to the completeness and disjunction of the hierarchy.</p>
<p>But this schema also presents certain problems. On one hand, if we have a city pool and want to know its name, we’ll need to access the Pool table to find its name, plus the CityPool table. This complicates the query and affects its efficiency and latency.</p>
<p>Aside from this, if we have a tuple from Pool and want to know if it’s a city pool, an Olympic pool, or neither, we’ll have to go through all the tuples in CityPool and OlympicPool to see if the foreign key of any of them points to the Pool tuple we are trying to identify.</p>
<p>Also, the presence of three tables is more complex than having just one or two, making the logical model somewhat more complicated to operate because there are more tables and more relationships between them.</p>
<h4 id="heading-when-to-model-each-entity-as-a-table">When to Model Each Entity as a Table</h4>
<p>These alternatives aren’t the only options for implementing an IS-A hierarchy at the logical level. Depending on the domain needs and requirements, we can choose other more appropriate schemas that are similar to those we’ve already discussed.</p>
<p>To summarize which is the best schema we can implement to model an IS-A hierarchy at the logical level, we need to know when it’s appropriate to introduce a table for each entity.</p>
<p>First, we have the <strong>superclass</strong>. This is useful to model with a specific table in cases where the hierarchy is incomplete, as in the example hierarchy. We saw that without a dedicated Pool table to represent occurrences of the superclass entity, it’s difficult to distinguish when a pool is of the generic type of the superclass or is instead of a specific type (like that of the inheriting entities). It’s also helpful to implement a table for the superclass when there is a foreign key pointing to the superclass entity itself. Otherwise, it’s very likely that we’ll have trouble knowing which attribute the foreign key should reference, as we saw before.</p>
<p>And to finish with the superclass, we should also implement a table for it when the hierarchy is <strong>non-disjoint</strong> or <strong>overlapping</strong>. For example, if a pool could be of several types at once and we didn't have the Pool table, we would be forced to duplicate information in specific tables for the inheriting entities. This would greatly complicate database operations.</p>
<p>So, with our Pool table, we can have tuples in the respective tables of the inheriting entities, all with their foreign keys pointing to the same Pool tuple, which simplifies queries.</p>
<p>If we have a Pool table where all existing pools are stored, it’s likely that we would want to efficiently know the type of a pool from a Pool tuple. Instead of having to go through all the tuples of the inheriting entities' tables, we can add an attribute in Pool that determines its type (if it has one). Or that will be NULL if the hierarchy is incomplete and doesn't belong to any type.</p>
<p>This is called an explicit discriminator. If there isn't one, we typically say that there is an implicit discriminator. These are the foreign keys of the other tables that we would have to go through to find out the type.</p>
<p>Regarding the inheriting entities, we should create a table for each one when they have many attributes, which would result in many NULL values if we were to implement this with just one or two tables. Besides the attributes, the inheriting entities themselves may have specific domain constraints that are greatly simplified at the logical level if we implement tables for each of them. This would avoid the need to apply constraints on just one or two tables, complicating the semantics of the constraints.</p>
<p>In short, the more entities we combine into a single table, the more NULL values we will encounter, since to <strong>distinguish</strong> them, the table attributes that do not correspond to the concept or entity we want to represent must be NULL, as if they don’t exist.</p>
<p>This would also complicate database operations, as operations would need to consider which attributes should or should not be NULL – as well as the constraints – which must account for the presence of NULL values to be verified.</p>
<p>On the other hand, if we know the hierarchy is complete, then instead of implementing a table for the superclass, we can decide to implement tables for each inheriting entity, where each one has the attributes of the superclass. But this option loses its purpose when we have a superclass with too many attributes, which would be repeated in several tables, potentially many.</p>
<h2 id="heading-chapter-7-normalization">Chapter 7: Normalization</h2>
<p>When trying to translate an IS-A hierarchy to the logical level, it's very likely that we’ll end up with a design that exhibits <strong>redundancy</strong>. This is because the same information, such as that of the superclass, can end up being stored in multiple places. This poses multiple problems in a database. So to understand it, let's consider the following example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>PersonID</strong></td><td><strong>PersonName</strong></td><td><strong>CityID</strong></td><td><strong>CityName</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Alice Johnson</td><td>1</td><td>Madrid</td></tr>
<tr>
<td>2</td><td>Bob Smith</td><td>5</td><td>Paris</td></tr>
<tr>
<td>3</td><td>Carol Davis</td><td>3</td><td>New York</td></tr>
<tr>
<td>4</td><td>David Brown</td><td>1</td><td>Madrid</td></tr>
<tr>
<td>5</td><td>Emily Wilson</td><td>5</td><td>Paris</td></tr>
</tbody>
</table>
</div><p>Here we have a Person table that stores data about people – specifically their ID, name, and the city where they live. But to represent the city, all the attributes that our database stores about cities are included in the Person table itself. This makes it so that in one row we can know information about the person as well as information about the city where they live.</p>
<p>At first glance, this may seem convenient, since if we have a Person row, we not only have all the information about the person but also all the information about the respective city. This then lets us avoid having to look up this information in other tables. But this creates a significant redundancy problem.</p>
<p>According to the definition of redundancy, it means that the same information is stored in multiple places, that is, repeated unnecessarily. And this doesn't mean the information has to be in different tables. For example, in this example we have redundancy because the same city information can be stored multiple times in the same Person table (as is the case with the city "Paris" or "Madrid").</p>
<p>This actually leads to problems when inserting new cities into the database. If we only store them in this table but don't have any person living in the city we want to insert, we won't be able to insert it unless we do so in a row of the Person table with the rest of the attributes that don't characterize a city set to NULL. And this will greatly complicate database operations.</p>
<p><strong>Redundancy also</strong> poses a problem for memory consumption, as duplicating all the information of a city for each person living there uses up unnecessary space. Similarly, if we want to delete a city or update its information, we have to do it for every instance where that information is repeated. This complicates operations and making them much less efficient.</p>
<p>For example, if we store a Population attribute in this table to represent each city's population, every time we update the population of a certain city, we have to do it for all the Person tuples. This becomes inefficient if many people live in that city, as we have to change the population data in all the tuples representing those people.</p>
<p>Just as it affects efficiency, redundancy also increases the chances of data inconsistency. If we forget to change one value when updating Population data, or if there's an error and a certain value in a tuple doesn't update, then that value will contradict the rest of the Population values in the repeated tuples for that city, causing an <strong>inconsistency</strong>.</p>
<p>To solve these types of situations, it's best to plan ahead by creating a good design at the conceptual level. We can try to separate concepts into entities that are distinct enough to avoid storing information about semantically different ideas in the same entity (as this could cause redundancy when moving to the logical level).</p>
<p>But if we reach the logical level with a certain diagram that we couldn't refine further at the conceptual level and we need to refine it, one of the transformations we can apply here is called decomposition.</p>
<h3 id="heading-decomposition">Decomposition</h3>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>PersonID</strong></td><td><strong>PersonName</strong></td><td><strong>CityID (FK)</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Alice Johnson</td><td>1</td></tr>
<tr>
<td>2</td><td>Bob Smith</td><td>5</td></tr>
<tr>
<td>3</td><td>Carol Davis</td><td>3</td></tr>
<tr>
<td>4</td><td>David Brown</td><td>1</td></tr>
<tr>
<td>5</td><td>Emily Wilson</td><td>5</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>CityID</strong></td><td><strong>Name</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Madrid</td></tr>
<tr>
<td>3</td><td>New York</td></tr>
<tr>
<td>5</td><td>Paris</td></tr>
</tbody>
</table>
</div><p>Before looking into what decomposition involves, it's helpful to examine the specific problems of combining information about people and cities in a single entity.</p>
<p>For example, if we store many attributes of a city, a lot of space will be wasted if we have many people living in that city. This is because all the city's attribute values are unnecessarily repeated in all the tuples of the people living there.</p>
<p>Another potential problem related to memory waste could happen if we needed to insert a person into the database and we don’t know the city they live in. This would force us to leave all the city's attributes as NULL, wasting all the space those NULLs occupy.</p>
<p>Similarly, if we delete all the people living in "Madrid," for example, then our database will no longer contain any information about that city, as no one lives there. This means it isn't explicitly stored in the table. Lastly, we previously saw the problems that arose when updating the information of a certain city.</p>
<p>As a solution to these issues, we can apply decomposition. If you consider the example above, you may be able to see that this involves breaking down the Person table into several tables. On one hand, we keep the Person table dedicated to storing information about people. On the other, for the cities, we store all their information in a specific City table.</p>
<p>Once the information is separated into multiple tables, we can maintain the <strong>CityID (FK)</strong> attribute in the Person table, where it’s now converted into a foreign key that references the <strong>CityID</strong> of the new <strong>City</strong> table, indicating the city where the person lives.</p>
<p>As you can see in the example, decomposition involves replacing one table with two or more tables, each containing a subset of the attributes from the original. By combining them, we can retrieve the original attributes.</p>
<p>For instance, here we have split one table into two, where one retains all the attributes related to people and the other holds attributes related to cities. Together, these attributes form the original table we had. We do this mainly to solve problems caused by redundancy. Now, in the Person table, we only store an identifier for the city where the person lives, and in the City table, we store the city's information only once, allowing it to be used by more tables in the database.</p>
<p>But in order to do decomposition correctly, we must ensure that certain conditions are met. One is that the decomposition is <strong>lossless</strong>. This means that if we now take the two tables generated by the decomposition and combine all their information back into a single table, we should get the information we had in the original Person table before the decomposition.</p>
<p>So if we now take the resulting Person table and add the information provided by the tuple from the City table identified by the foreign key defined in the decomposition to each tuple, we should get the same information as we had in the original Person table before the decomposition – without losing any tuples or creating new ones.</p>
<p>This join operation easily shows that it returns the data we originally had before the decomposition. And this indicates that the decomposition was done without loss. But this doesn't guarantee it will be lossless for any possible tuple. To ensure this, we need to analyze the <strong>functional dependencies</strong> present among the table's attributes, which must also be preserved after decomposition.</p>
<p>Lastly, when performing the decomposition, we might receive queries in the database such as, given a person, obtaining information about the city they live in. To implement this query, we usually perform operations similar to the join we described earlier, which can be computationally expensive. So if it becomes so costly that it's impractical, we might consider not doing the decomposition. Or we could even doing a partial one, where we keep the city attributes that are queried most frequently in the Person table to make certain queries more efficient, even if some redundancy exists.</p>
<h3 id="heading-functional-dependency">Functional dependency</h3>
<p>Continuing with these conditions, to understand them correctly, you’ll need to know what functional dependencies are.</p>
<p>To introduce this concept, we can look at the simplest case, which is the attributes PersonID and PersonName of the Person table. These store a person's government identification number and their name, respectively. So if we find several tuples in the Person table with the same PersonID value, we would expect their respective PersonName values to also be the same. This is because if several tuples store information about people with the same ID, then they must necessarily be the same person (as we assume the government identification number is unique for each person).</p>
<p>So whenever there are several tuples with the same ID, we can say that the names of the people represented by those tuples must also be the same.</p>
<p>But the reverse does not have to be true, because if several different people have the same name, they will have the same name but different IDs. So if several tuples have the same PersonName, their respective PersonIDs do not have to match.</p>
<p>This situation we just saw is a case of functional dependency between <strong>PersonID</strong> and <strong>PersonName</strong>, specifically denoted as <strong>PersonID→PersonName</strong>, since it’s the PersonID attribute that uniquely determines the person's name.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>PersonID</strong></td><td><strong>PersonName</strong></td><td><strong>CityID</strong></td><td><strong>CityName</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Alice Johnson</td><td>1</td><td>Madrid</td></tr>
<tr>
<td>2</td><td>Bob Smith</td><td>5</td><td>Paris</td></tr>
<tr>
<td>3</td><td>Carol Davis</td><td>3</td><td>New York</td></tr>
<tr>
<td>4</td><td>David Brown</td><td>1</td><td>Madrid</td></tr>
<tr>
<td>5</td><td>Emily Wilson</td><td>5</td><td>Paris</td></tr>
</tbody>
</table>
</div><p>Formally, we can define a functional dependency as a constraint or relationship that exists between two sets of attributes, such that the values taken by one set of attributes uniquely determine the values that the other set of attributes must take.</p>
<p>For example, using the same example without decomposing, we can see that there is a functional dependency between the set of attributes <strong>X={PersonID}</strong> and the set <strong>Y={PersonName}</strong>, denoted as <strong>X→Y.</strong> This means that for any pair of tuples in the table, if those tuples have the same values in the set of attributes X, then they must necessarily have the same values in the set of attributes Y.</p>
<p>But we don't discover this by simple observation. These dependencies are mainly given by the characteristics of the attributes and the domain we are modeling, as well as the requirements. That is, to discover these dependencies, we need to focus on the semantics of the attributes.</p>
<p>The formal definition of this concept states that a functional dependency is a relationship between sets of attributes, so they don't have to be single-attribute sets – they can contain any number of them, depending on the complexity of the dependency.</p>
<p>For example, if we assume that a person always lives in the same house and never moves, then we can say there is a functional dependency <strong>{PersonID}→{CityID}</strong>, as well as <strong>{PersonID}→{CityName}</strong>. This results in functional dependencies for all possible combinations of attributes on the right-hand side, which must take the same value for several tuples if they have the same value for the attributes on the left-hand side.</p>
<p>Specifically, this means that given the dependencies we know exist, the following also exist:</p>
<ul>
<li><p><strong>{PersonID}→{PersonName,CityID}</strong></p>
</li>
<li><p><strong>{PersonID}→{PersonName,CityName}</strong></p>
</li>
<li><p><strong>{PersonID}→{CityID,CityName}</strong></p>
</li>
<li><p><strong>{PersonID}→{CityID,CityName,PersonName}</strong></p>
</li>
</ul>
<p>This occurs due to the union property of functional dependencies, where if we have dependencies <strong>X→Y</strong> and <strong>X→Z</strong>, then the dependency <strong>X→(Y U Z)</strong> also exists, where the uppercase letters denote sets of attributes.</p>
<p>Without going into more detail about these properties, it's worth highlighting that this is one of Armstrong's inference rules, whose main purpose is to <strong>infer all the functional dependencies</strong> that exist in a table. Specifically, these inference rules ensure that, starting from a series of initial functional dependencies, <strong>all</strong> the dependencies that actually exist in a table can be inferred.</p>
<p>With this, the important thing to know is that functional dependencies can have multiple attributes in their sets. This in turn can lead to a classification of the dependencies based on the number of attributes they have in each set.</p>
<p>One of the main uses of functional dependencies is to determine if a decomposition is valid, meaning if all the functional dependencies are preserved.</p>
<p>For example, in the original table, there are the functional dependencies <strong>{PersonID}→{PersonName}</strong> and <strong>{PersonID}→{CityID}</strong>, primarily, or <strong>{CityID}→{CityName}</strong> because the identifier of a city uniquely determines the name of the city itself. So, considering these dependencies as a base, we can infer others like <strong>{PersonID}→{CityName}</strong> by transitivity using <strong>{PersonID}→{CityID}</strong> and <strong>{CityID}→{CityName}</strong>.</p>
<p>The ones we have considered as base are those generated directly by the domain's semantics. This means that if a city is uniquely identified by its <strong>CityID</strong>, then it doesn't make sense to consider <strong>{PersonID}→{CityName}</strong> as a base, since we have the other dependencies that relate the person's identifier with their name and city identifier, from which we can infer it.</p>
<p>In summary, the base dependencies are the most fundamental ones from which all others can be inferred. There is no single algorithm to find them all. Instead, it’s a more open process that we need to follow based on our domain, requirements, and the semantics of the attributes.</p>
<p>Once we’ve found the base dependencies, the important thing is to ensure that they are preserved after decomposing a table. We can see this in the resulting tables, where <strong>{PersonID}→{PersonName}</strong> remains in Person, as does <strong>{PersonID}→{CityID}</strong>, with the only peculiarity being that now CityID in Person is a foreign key, and <strong>{CityID}→{CityName}</strong>, which is preserved in the new City table after decomposition.</p>
<p>So by preserving all the base functional dependencies, we are assured that the decomposition of Person into Person and City is correct.</p>
<p>Finally, functional dependencies can have many more classifications besides being base or not. For example, in some of the formal definitions of the following normal forms that we’ll see, we often check if a functional dependency is trivial. This consists of those dependencies X→Y where all the attributes of set Y are present in set X.</p>
<p>For example, <strong>{A, B} → {A}</strong> is trivial because {A} ⊆ {A, B}, and <strong>{A, B} → {B, A}</strong> is also trivial because {B, A} ⊆ {A, B}. But <strong>{A} → {B}</strong> is <strong>not</strong> trivial because {B} ⊄ {A}, meaning there is an attribute in set {B} that is not present in set {A}.</p>
<h3 id="heading-normal-forms">Normal forms</h3>
<p>After understanding what functional dependencies are, it's important to note that there are many other types of dependencies, such as multivalued, union, or inclusion dependencies. All of these also aim to eliminate or minimize the problems associated with data redundancy that we saw earlier through normal forms.</p>
<p>These are a series of refinement levels of a relational schema defined by increasingly strict conditions intended to eliminate or progressively minimize the issues caused by redundancy in a schema. Among all the levels, we will only look at those that use functional dependencies between attributes as criteria for their conditions. But there are others we won’t cover here whose criteria include multivalued or union dependencies.</p>
<h4 id="heading-1nf">1NF</h4>
<p>First, we have the <strong>first normal form (1NF)</strong>, whose main condition is that each attribute is <strong>atomic</strong>. This means that the table cells do not contain an arbitrary number of values, which we can also call the non-existence of repeating groups. But it also imposes basic conditions such as the requirement for a primary key in the table so that each tuple can be uniquely identified. This prohibits duplicate tuples, as well as attributes with duplicate names, meaning there can’t be columns with duplicate names.</p>
<p>These conditions must be met for all tables in a database schema to be in 1NF. In this case, we can easily verify them by ensuring that each cell contains exactly one value, that there are no duplicates in rows or columns, and that there is a primary key.</p>
<p>These last three conditions are allowed by a DBMS, which means that when implementing a table at the logical level, we can have duplicates or even not define any key – and although the database may function, its schema won’t be in 1NF. So if we find a table that does not meet the normal form conditions, we can apply certain transformations to normalize it and bring it to 1NF.</p>
<h4 id="heading-2nf">2NF</h4>
<p>The first normal form focuses mainly on prohibiting repeating groups, which eliminates the possibility of redundancies at the cell level – but does not eliminate redundancies caused by functional dependencies.</p>
<p>Despite prohibiting the existence of duplicate tuples, we saw in a previous example that city information in a table could be unnecessarily duplicated in multiple different tuples because the people living in that city were different. This meets 1NF but presents redundancy problems.</p>
<p>To address these redundancy cases, we use the <strong>second normal form (2NF)</strong>. It includes all the conditions of 1NF plus an additional stricter condition: all attributes that aren’t the primary key of a table must depend on the <strong>entire selected primary key</strong> for the table – meaning all its attributes, not just one. This prevents partial dependency on the primary key.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>BikeID</strong></td><td><strong>Model</strong></td><td><strong>Brand</strong></td><td><strong>BrandCountry</strong></td><td><strong>PurchasePrice</strong></td><td><strong>OwnerName</strong></td><td><strong>OwnerEmail</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Roadster</td><td>SpeedX</td><td>USA</td><td>1200</td><td>John Doe</td><td>john@example.com</td></tr>
<tr>
<td>2</td><td>TrailBlazer</td><td>MountainCo</td><td>Canada</td><td>1500</td><td>Alice Smith</td><td>alice@example.com</td></tr>
<tr>
<td>3</td><td>Roadster</td><td>SpeedX</td><td>USA</td><td>1150</td><td>Bob Lee</td><td>bob@example.org</td></tr>
<tr>
<td>4</td><td>CityCruiser</td><td>UrbanRide</td><td>USA</td><td>800</td><td>John Doe</td><td>john@example.com</td></tr>
<tr>
<td>5</td><td>EcoCruiser</td><td>GreenMotion</td><td>Germany</td><td>1300</td><td>Carol Johnson</td><td>carol@example.com</td></tr>
</tbody>
</table>
</div><p>For example, here we have a Bike table whose primary key is {BikeID}, and the basic functional dependencies are {BikeID}→{Model}, {BikeID}→{PurchasePrice}, {BikeID}→{OwnerName}, {BikeID}→{OwnerEmail} because if BikeID uniquely identifies each bike, then the information about the model, price, and owner will directly depend on that attribute.</p>
<p>We also have the dependencies {Model}→{Brand}, {Model}→{BrandCountry}, and {OwnerEmail}→{OwnerName}, since knowing the bike model can uniquely determine its brand. We can also determine the owner's name from their email, which we can’t do in reverse because multiple people can have the same name and different email addresses.</p>
<p>Given these dependencies, since the primary key has only one attribute, we see that all others have a dependency on the entire primary key. This means that the primary key itself uniquely determines the rest of the table's attributes. So we can formally denote that, for all attributes A that aren’t the primary key, there’s the functional dependency <strong>{Primary Key}→A</strong>.</p>
<p>In this case, even though some dependencies are transitive, we can see that in the end, all attributes end up depending on the primary key. For example, with {BikeID}→{Model} and {Model}→{Brand}, we infer the dependency {BikeID}→{Brand}, which is not basic.</p>
<p>When this condition is met, the table is in 2NF, which avoids redundancies caused by attributes that depend only on part of the primary key, not the whole key.</p>
<p>This might not be as clear here because the primary key in the example has only one attribute, but sometimes we have primary keys with more attributes. In such cases, the rest of the table's attributes must depend on all the attributes in the primary key in order to be in 2NF (in addition to meeting the conditions of 1NF).</p>
<p>If they depend only on part of the key, there could be repeated values in those attributes. This would cause redundancy issues because it’s the entire primary key (all its attributes) that can uniquely identify each tuple.</p>
<h4 id="heading-3nf">3NF</h4>
<p>Continuing with normal forms, <a target="_blank" href="https://cse.hkust.edu.hk/~dimitris/5311/L08.pdf"><strong>3NF</strong></a> is defined similarly. First, for a schema to be in 3NF, it must meet all the conditions of 2NF plus a specific one that states there can’t be functional dependencies between non-prime attributes.</p>
<p>Prime attributes are those that belong to any candidate key of the table. So we can restate the previous condition of 3NF by saying that no attribute that does not belong to any candidate key can functionally depend on any other attribute that does not belong to any candidate key.</p>
<p>For example, in the Bike table we had earlier, we assume that the only candidate key that exists is <strong>{BikeID}</strong>, since no other set of attributes can uniquely identify the tuples in the table. We can verify this by looking at the semantics of the attributes. So, seeing that there are functional dependencies like <strong>{Model}→{BrandCountry}</strong> between non-prime attributes, meaning they do not belong to any candidate key, we conclude that the table is not in 3NF, and we’ll need to normalize it.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>BikeID</strong></td><td><strong>Model (FK)</strong></td><td><strong>PurchasePrice</strong></td><td><strong>OwnerEmail (FK)</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Roadster</td><td>1200</td><td>john@example.com</td></tr>
<tr>
<td>2</td><td>TrailBlazer</td><td>1500</td><td>alice@example.com</td></tr>
<tr>
<td>3</td><td>Roadster</td><td>1150</td><td>bob@example.org</td></tr>
<tr>
<td>4</td><td>CityCruiser</td><td>800</td><td>john@example.com</td></tr>
<tr>
<td>5</td><td>EcoCruiser</td><td>1300</td><td>carol@example.com</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Model</strong></td><td><strong>Brand</strong></td><td><strong>BrandCountry</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Roadster</td><td>SpeedX</td><td>USA</td></tr>
<tr>
<td>TrailBlazer</td><td>MountainCo</td><td>Canada</td></tr>
<tr>
<td>Roadster</td><td>SpeedX</td><td>USA</td></tr>
<tr>
<td>CityCruiser</td><td>UrbanRide</td><td>USA</td></tr>
<tr>
<td>EcoCruiser</td><td>GreenMotion</td><td>Germany</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>OwnerEmail</strong></td><td><strong>OwnerName</strong></td></tr>
</thead>
<tbody>
<tr>
<td>john@example.com</td><td>John Doe</td></tr>
<tr>
<td>alice@example.com</td><td>Alice Smith</td></tr>
<tr>
<td>bob@example.org</td><td>Bob Lee</td></tr>
<tr>
<td>john@example.com</td><td>John Doe</td></tr>
<tr>
<td>carol@example.com</td><td>Carol Johnson</td></tr>
</tbody>
</table>
</div><p>To normalize the table, we’ll need to apply an algorithm to the tables to convert the schema to 3NF, ensuring there are no functional dependencies between non-prime attributes.</p>
<p>To understand this algorithm, we’ll start with the original Bike table we had before. We’ll on the functional dependencies between prime attributes that break 3NF, that aren’t derived transitively from simpler ones, and whose set of attributes on the left side does not form a superkey.</p>
<p>For example, if we have {A}→{B}, {B}→{C}, and {A}→{C}, we do not consider {A}→{C} since it can be derived transitively from the other two. Specifically, the problematic ones in our example, which aren’t derived transitively and whose left side is not a superkey, are {Model}→{Brand}, {Model}→{BrandCountry}, and {OwnerEmail}→{OwnerName}, which are the base functional dependencies.</p>
<p>Now, we need to decompose the table guided by these functional dependencies. But as you can see, we can apply the union property of functional dependencies to know that the <strong>functional dependency</strong> <strong>{Model}→{Brand, BrandCountry}</strong> also exists. We derived it from the previous problematic ones to simplify the application of the algorithm.</p>
<p>In short, to make the algorithm easier to apply, whenever we see multiple functional dependencies with the same determinant (set of attributes on the left side), it’s useful to apply the union property mentioned earlier to simplify them into one.</p>
<p>So now we have that the problematic functional dependencies are <strong>{Model}→{Brand, BrandCountry}</strong> and <strong>{OwnerEmail}→{OwnerName}</strong>. We can create a specific table for each of them where its schema is made up of all the attributes of the dependency – that is, all the attributes on both sides. We can formally denote this as the union of both sets of attributes.</p>
<p>As you might guess, by doing this, the primary keys in the new tables will be the attributes of the determinants of these dependencies (which in this case are <strong>{Model}</strong> and <strong>{OwnerEmail}</strong>, respectively).</p>
<p>We also need to remove these attributes that we have separated into additional tables from the original Bike table, leaving only the attributes of the determinants of these dependencies and converting them into foreign keys to reference the corresponding primary keys of the new tables. By convention, the attributes that make up the primary key of a table are usually placed first on the left, like <strong>Model</strong> and <strong>OwnerEmail</strong> here.</p>
<p>After this process, we can see that all the functional dependencies that were previously problematic are now in new tables where their determinants are now primary keys. This avoids violating the condition imposed by 3NF.</p>
<p>Note that after applying this algorithm, we don’t need to apply it recursively to the tables generated by the decomposition, as there is a guarantee that the resulting schema is already in 3NF after applying this process. In summary, by applying this normal form to our schema using the described algorithm, known as the <a target="_blank" href="https://www.cs.emory.edu/~cheung/Courses/377/Syllabus/9-NormalForms/FD-preserve-howto.html"><strong>relational synthesis algorithm</strong></a>, we manage to avoid or minimize the occurrence of redundancies caused by transitive functional dependencies.</p>
<h3 id="heading-bcnf">BCNF</h3>
<p>The three previous normal forms are the most basic ones we can apply to a schema to eliminate most problems caused by redundancies. But there is another normal form in addition to 3NF that is more restrictive and ensures a better result in this regard, which is <strong>BCNF</strong>.</p>
<p>As we’ve seen, the normal forms become increasingly restrictive in the conditions they apply. In this case, <a target="_blank" href="https://cs.stackexchange.com/questions/116901/database-theory-does-the-dependency-preservation-and-lossless-join-properties"><strong>BCNF</strong> stands for <strong>Boyce-Codd Normal Form</strong></a>, and it’s characterized by allowing only those functional dependencies <strong>X→Y</strong> in the tables where it’s true that either the dependency is <strong>trivial</strong> or X is a <strong>superkey</strong> of the table.</p>
<p>If these conditions are met, we can formally demonstrate that all the conditions of 3NF must also be automatically met (and so also 2NF and 1NF). We won’t perform this demonstration here, as the important thing is to know how to normalize a schema to adhere to the BCNF. So if we start with a schema like the one we originally had for the unnormalized Bike table, we can apply a specific algorithm to transform it to BCNF.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>BikeID</strong></td><td><strong>Model</strong></td><td><strong>Brand</strong></td><td><strong>BrandCountry</strong></td><td><strong>PurchasePrice</strong></td><td><strong>OwnerName</strong></td><td><strong>OwnerEmail</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Roadster</td><td>SpeedX</td><td>USA</td><td>1200</td><td>John Doe</td><td>john@example.com</td></tr>
<tr>
<td>2</td><td>TrailBlazer</td><td>MountainCo</td><td>Canada</td><td>1500</td><td>Alice Smith</td><td>alice@example.com</td></tr>
<tr>
<td>3</td><td>Roadster</td><td>SpeedX</td><td>USA</td><td>1150</td><td>Bob Lee</td><td>bob@example.org</td></tr>
<tr>
<td>4</td><td>CityCruiser</td><td>UrbanRide</td><td>USA</td><td>800</td><td>John Doe</td><td>john@example.com</td></tr>
<tr>
<td>5</td><td>EcoCruiser</td><td>GreenMotion</td><td>Germany</td><td>1300</td><td>Carol Johnson</td><td>carol@example.com</td></tr>
</tbody>
</table>
</div><p>The algorithm to convert to BCNF is very similar to the one we looked at for 3NF. The difference is that here, the decomposition is done in more steps.</p>
<p>First, we need to identify the functional dependencies that prevent compliance with BCNF, which are exactly {Model}→{Brand}, {Model}→{BrandCountry}, and {OwnerEmail}→{OwnerName}. We choose these because, as you can see, {Model} can’t be a superkey, nor can {OwnerEmail} on its own. But in other functional dependencies like {BikeID}→{PurchasePrice}, we see that {BikeID} is indeed a superkey, as it’s actually the primary key of the table. So we don’t include those when applying the algorithm.</p>
<p>Also, keep in mind that a functional dependency X→Y can be trivial and meet the definition of BCNF even if X is not a superkey, meaning that the set of attributes Y is a subset of the set of attributes X.</p>
<p>Now, to simplify the application of the algorithm, we can focus on the determinant of the dependencies that break the normal form – that is, on the set of attributes on the left side, looking for several that have the same determinant. If there are several with the same determinant, as is the case with those that have <strong>{Model}</strong> on their left side, then we can use the union property of Armstrong's inference rules to simplify them all into one like <strong>{Model}→{Brand,BrandCountry}</strong>. Here', on the right side, we have gathered all the attributes from the right sides of the dependencies we had.</p>
<p>In this way, we reduce the number of dependencies to consider in the algorithm which simplifies its execution. This is the case since this step is not mandatory in this algorithm (nor in the conversion to 3NF), as it’s not part of the algorithm's definition itself, but rather something additional we do to simplify it without affecting its correctness.</p>
<p>Afterward, we end up with the dependencies <strong>{Model}→{Brand,BrandCountry}</strong> and <strong>{OwnerEmail}→{OwnerName}</strong>, which guide the decomposition we will perform on the table, similar to the 3NF conversion algorithm. But the main difference is that now we select the dependencies one by one and perform a decomposition for each, not all at once. Each time the table is decomposed, the dependencies and keys change, so we have to do it one by one to ensure that the recombination of the decomposed tables remains lossless.</p>
<p>Although we won't go into detail about why this happens, the important thing to remember is that we use this method because this algorithm doesn’t guarantee the preservation of all functional dependencies due to the conditions that define this normal form. These conditions are restrictive enough that, in certain situations, some dependencies may not be preserved after decomposition.</p>
<p>When selecting one of the dependencies like <strong>{Model}→{Brand,BrandCountry}</strong> (we can actually choose any of them), we decompose the Bike table guided by this functional dependency. We remove all the attributes on the right side of the dependency from the original table and make the attributes of the determinant (left side) foreign keys. These foreign keys point to the corresponding attributes of a new table where we store all the attributes involved in the dependency (meaning from both sides).</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>BikeID</strong></td><td><strong>Model (FK)</strong></td><td><strong>PurchasePrice</strong></td><td><strong>OwnerName</strong></td><td><strong>OwnerEmail</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Roadster</td><td>1200</td><td>John Doe</td><td>john@example.com</td></tr>
<tr>
<td>2</td><td>TrailBlazer</td><td>1500</td><td>Alice Smith</td><td>alice@example.com</td></tr>
<tr>
<td>3</td><td>Roadster</td><td>1150</td><td>Bob Lee</td><td>bob@example.org</td></tr>
<tr>
<td>4</td><td>CityCruiser</td><td>800</td><td>John Doe</td><td>john@example.com</td></tr>
<tr>
<td>5</td><td>EcoCruiser</td><td>1300</td><td>Carol Johnson</td><td>carol@example.com</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Model</strong></td><td><strong>Brand</strong></td><td><strong>BrandCountry</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Roadster</td><td>SpeedX</td><td>USA</td></tr>
<tr>
<td>TrailBlazer</td><td>MountainCo</td><td>Canada</td></tr>
<tr>
<td>Roadster</td><td>SpeedX</td><td>USA</td></tr>
<tr>
<td>CityCruiser</td><td>UrbanRide</td><td>USA</td></tr>
<tr>
<td>EcoCruiser</td><td>GreenMotion</td><td>Germany</td></tr>
</tbody>
</table>
</div><p>Formally, if our original table is the set of attributes <strong>R</strong>, then we keep <strong>R-{Brand,BrandCountry}</strong>, convert <strong>{Model}</strong> into the foreign key <strong>{Model (FK)}</strong> referencing the set of attributes {Model} of the new table generated by the decomposition, whose attributes are given by <strong>{Model}U{Brand,BrandCountry}</strong>, and whose primary key is the set <strong>{Model}</strong> that was previously in the <strong>determinant</strong> of the dependency.</p>
<p>Now, we repeat this process recursively on the resulting tables, as this decomposition has solved the problem caused by the dependency {Model}→{Brand,BrandCountry}. But we still have the dependency {OwnerEmail}→{OwnerName} in the Bike table. So we apply another decomposition step guided by the only remaining dependency that violates the BCNF conditions.</p>
<p>By doing this, we remove the set of attributes {OwnerName} from the Bike table and convert {OwnerEmail} into a foreign key that references the same set {OwnerEmail} but from the new table generated by the decomposition. In this case it’s formed by the attributes <strong>{OwnerEmail}U{OwnerName}={OwnerEmail,OwnerName}</strong>.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>BikeID</strong></td><td><strong>Model (FK)</strong></td><td><strong>PurchasePrice</strong></td><td><strong>OwnerEmail (FK)</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Roadster</td><td>1200</td><td>john@example.com</td></tr>
<tr>
<td>2</td><td>TrailBlazer</td><td>1500</td><td>alice@example.com</td></tr>
<tr>
<td>3</td><td>Roadster</td><td>1150</td><td>bob@example.org</td></tr>
<tr>
<td>4</td><td>CityCruiser</td><td>800</td><td>john@example.com</td></tr>
<tr>
<td>5</td><td>EcoCruiser</td><td>1300</td><td>carol@example.com</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Model</strong></td><td><strong>Brand</strong></td><td><strong>BrandCountry</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Roadster</td><td>SpeedX</td><td>USA</td></tr>
<tr>
<td>TrailBlazer</td><td>MountainCo</td><td>Canada</td></tr>
<tr>
<td>Roadster</td><td>SpeedX</td><td>USA</td></tr>
<tr>
<td>CityCruiser</td><td>UrbanRide</td><td>USA</td></tr>
<tr>
<td>EcoCruiser</td><td>GreenMotion</td><td>Germany</td></tr>
</tbody>
</table>
</div><div class="hn-table">
<table>
<thead>
<tr>
<td><strong>OwnerEmail</strong></td><td><strong>OwnerName</strong></td></tr>
</thead>
<tbody>
<tr>
<td>john@example.com</td><td>John Doe</td></tr>
<tr>
<td>alice@example.com</td><td>Alice Smith</td></tr>
<tr>
<td>bob@example.org</td><td>Bob Lee</td></tr>
<tr>
<td>john@example.com</td><td>John Doe</td></tr>
<tr>
<td>carol@example.com</td><td>Carol Johnson</td></tr>
</tbody>
</table>
</div><p>As you can see, after these steps, the schema doesn’t have any functional dependency <strong>X→Y</strong> where X is not a superkey or the dependency itself is trivial. This is because when decomposing into tables, we define their primary keys as the determinants of the dependencies that originally did not comply with the normal form.</p>
<p>So after performing these steps for all dependencies that prevent the schema from adhering to BCNF, we end up with a normalized schema that does comply with BCNF. During the process, it’s possible that some of the generated tables still have functional dependencies that violate BCNF, which is why these steps are applied recursively. This means that decomposition is not only done from the original table, but it may also be necessary to decompose a table generated by previous steps, especially in more complex schemas.</p>
<p>In the example we have, the final schema that meets the BCNF conditions is exactly the same as the one we got when transforming it to BCNF. But this is a coincidence – in most practical cases, schemas tend to be more complex, and after converting them to 3NF, they may not comply with BCNF, or it may even be impossible to convert them to BCNF. That is, converting a schema to 3NF is always guaranteed to be possible, while there is no such guarantee for BCNF.</p>
<p>In short, BCNF is more restrictive than 3NF, which prevents redundancies caused by functional dependencies where a set of attributes that do not uniquely identify the tuples of a table determine the values of another set of attributes. This makes the information of the determining attributes redundant, similar to what happens in 3NF with transitive dependencies.</p>
<p>Also, being more restrictive, it may not be achievable if a table has multiple overlapping superkeys, as applying the <strong>BCNF decomposition algorithm</strong> would break the functional dependencies between attributes of different superkeys. So by relaxing the conditions of BCNF, we get 3NF, which correctly handles situations where overlapping superkeys exist, meaning they share some attribute.</p>
<h3 id="heading-other-normal-forms">Other normal forms</h3>
<p>Besides the normal forms based on functional dependencies, which we have just seen, there are others that eliminate redundancies caused by different types of relationships between attributes or characteristics.</p>
<p>For example, <strong>4NF</strong> deals with <strong>multivalued dependencies</strong>, 5NF with join dependencies, <strong>6NF</strong> represents the highest level of normalization of a relational schema, and <strong>DKNF (Domain–Key Normal Form)</strong> also imposes the condition that all schema constraints must result solely from domain and key definitions, meaning it only allows domain and key constraints.</p>
<h3 id="heading-when-to-check-compliance-with-each-normal-form">When to check compliance with each normal form?</h3>
<p>Lastly, we’ve seen that each normal form establishes a series of characteristics that a <strong>database schema</strong> has to follow and the problems it aims to solve.</p>
<p>Practically speaking, the most important normal forms we need to ensure for almost any schema are <strong>1NF</strong> and <strong>2NF</strong>. In the case of 1NF, most DBMSs guarantee it automatically – but we have to design the conceptual model so that it avoids the appearance of repeating groups that don’t meet the conditions of 1NF. On the other hand, 2NF is essential for identifying tuples in tables, so we should make sure it’s met in a real project database.</p>
<p>Beyond these, if we’re working with a system that performs analytical queries like in <strong>OLTP</strong>, the database schema should also meet the conditions of 3NF, especially when the schema needs to handle queries or undergo updates frequently. This helps resolve these queries and updates as efficiently as possible.</p>
<p>Beyond 3NF, we’ll want to meet BCNF when business rules are very complex. That is, when data has to meet complex constraints, we can help minimize the impact of redundancy issues through BCNF conditions, as they are more restrictive than those of 3NF. Then, if our schema allows <strong>multivalued attributes</strong> or associations of <strong>degree</strong> higher than 2, it may be useful to check other types of normal forms like 4NF, 5NF, and so on.</p>
<h2 id="heading-chapter-8-query-languages">Chapter 8: Query Languages</h2>
<p>At this point, you’ve learned about all the elements with which we can organize or structure stored data in relational databases using the relational model. But in practice, we don’t only want to store data, as we could do that with simple files. We also need tools to manipulate and query these data. This means we need to use a query language.</p>
<p>In simple terms, <strong>query languages</strong> are designed to manipulate and query (or access) the data stored in a database through a set of operations. Querying is the most fundamental operation of all, because if we think about how some of the other operations work (like updating or deleting data, for example), we need to be able to select or query the data in order to perform any operations on them. So basically, almost any modification starts by first identifying which records will be affected by the operation.</p>
<p>The query languages we’ll learn about here are <strong>relational</strong>, meaning they are created to manipulate and query data in relational databases. Fundamentally, most of them base the logic of operations on table manipulations that result in another table. Then we can continue applying operations to that resulting table. So when we operate on a relational database, we are transforming tables into other tables until we reach a table with data that interests us.</p>
<h3 id="heading-formal-vs-practical-query-languages">Formal vs practical query languages</h3>
<p>There are some query languages known as formal languages, which consist of theoretical definitions where operators or transformations that can be applied to tables are formally defined. This also helps optimize operations on them significantly, as these formal tools allow us to verify equivalences between operations or queries, enabling us to choose the one with the least computational cost among several equivalents.</p>
<p>On the other hand, to apply this to a database, there are practical query languages like <a target="_blank" href="https://www.freecodecamp.org/news/an-animated-introduction-to-sql-learn-to-query-relational-databases/"><strong>SQL</strong></a>, which are implementations of formal query languages adapted to be used on real systems.</p>
<p>Although we call them languages, it's important not to confuse them with general-purpose languages. Query languages, as their name suggests, are dedicated to manipulating and querying data, not performing any type of computation. Examples of formal query languages include:</p>
<h4 id="heading-relational-algebra">Relational algebra</h4>
<p>This is a formal imperative language, which means that when we program in it, we must think about how to obtain the result we want. In other words, we define a sequence of operations using the language's operators that progressively transform the tables until we reach one or more resulting tables with the data we need.</p>
<p>This idea of a sequence of operations is very similar to how we’d actuall plan and execute a query in a practical query language like SQL. This, along with the similarity of formal operators to the statements offered by these practical languages, helps the end user optimize the query, verify its correctness formally, or demonstrate its equivalence with another query that requires fewer computational resources, among other uses.</p>
<ul>
<li><strong>Example:</strong> If we want to get all the ages from a Person table that are greater than 50, we can apply the relational algebra operators <strong>π Age ( σ (Age &gt; 50) (Person) )</strong> that we will see later. First, we filter all tuples that meet the condition of having an age &gt;50 using the corresponding operator, and then we apply another operator to the resulting table with those tuples to keep only the ages of those tuples.</li>
</ul>
<h4 id="heading-relational-calculus">Relational calculus</h4>
<p>Unlike the relational algebra, relational calculus is a declarative language. This means we program by thinking about the properties the result must have, not about which operators to apply to certain tables to achieve it. In other words, we don’t define something similar to an execution plan or sequence of operators to get the result. Instead, we simply declare the properties it must have to meet our needs, and the system itself finds an execution plan that produces exactly what we are looking for.</p>
<p>There are several ways to pose a query or modification on the data. One is based on <strong>Tuple Relational Calculus (TRC)</strong>, where we declare conditions that the attributes of the tuples must meet to be included in our result. The other is <strong>Domain Relational Calculus (DRC)</strong>, which involves using variables over the domains of the attributes to set conditions on them using a methodology similar to first-order logic.</p>
<ul>
<li><strong>Example:</strong> Following the same example as before, in <strong>TRC</strong> we would have something like <strong>{ t.Age | Person(t) ∧ t.Age &gt; 50 }</strong>, where we declare that the tuples <strong>t</strong> we want to obtain must belong to the Person table and have a value greater than 50 in the Age attribute. Meanwhile, in <strong>DRC</strong> we would have <strong>{ ⟨a⟩ | ∃id ( Person(id, a) ∧ a &gt; 50) }</strong>, where we are assuming that the table only stores an ID attribute and an Age attribute, because if more were stored, we would have to use more domain variables. In summary, here the conditions are imposed on the domain variables, which represent the values that the tuples take in their respective attributes.</li>
</ul>
<p>Lastly, regardless of the formal language used, both have the same expressive capacity, which can be formally demonstrated, as both are constructed using first-order logic.</p>
<h2 id="heading-chapter-9-sql-structured-query-language">Chapter 9: SQL (Structured Query Language)</h2>
<p>In addition to formal languages, there are implementations like Structured Query Language (SQL) that are based on the operations of these formal languages. They allow us to manipulate and query data through relational database management systems (DBMS).</p>
<p>Specifically, SQL is a commercially used language with various standards, to which various functionalities have been added over time. Most systems have versions installed that are newer than SQL-92. But that version already includes all the necessary functions to perform the vast majority of operations needed on a database, so it’s the standard we’ll explore here. And while we aim for portable SQL, several examples use features introduced after SQL-92 or PostgreSQL-specific extensions (like <code>BOOLEAN</code>, <code>XML/JSON</code>, <code>UUID</code>, and psql meta-commands).</p>
<p>SQL is a declarative language, where we define what data we want to get, not the exact sequence of operations to get it. The DBMS does the latter internally by translating the statements we write into relational algebra operations, which transform the tables through an execution plan until reaching the final resulting table.</p>
<p>Before proceeding with the elements that make up the SQL language itself, we should distinguish these elements or statements based on their purpose or application area.</p>
<p>On one hand, we have the statements that form the Data Definition Language (DDL), which is a set of statements dedicated to managing the tables in the database (such as their creation, deletion, modification, and so on).</p>
<p>Then we have the Data Control Language (DCL), which is another set of language statements dedicated to controlling user permissions in the database, managing who can read or modify the tables.</p>
<p>On the other hand, we have the Data Manipulation Language (DML). Its statements are oriented towards managing the data contained in the tables, such as insertion, deletion, transformation, or querying.</p>
<p>Apart from these sets of statements or instructions, we can also consider the <a target="_blank" href="https://www.geeksforgeeks.org/sql/tcl-full-form/"><strong>Transaction Control Language (TCL)</strong></a>, which are a series of statements that allow us to manage transactions that occur in the database. Here, we will focus only on the first three sets, which contain the most fundamental instructions.</p>
<h3 id="heading-ddl">DDL</h3>
<p>To start with SQL, the most basic thing we can do is create, modify, and delete tables in the database. This means that we use instructions that allow us to define our logical design in the DBMS.</p>
<p>Here, we’ll use <strong>PostgreSQL</strong> as the DBMS, although these examples can be applied to any DBMS that supports the <strong>SQL-92</strong> standard, which is what we will focus on.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752248008262/339c85d9-14a2-4d63-9453-c0f1a36e90f0.png" alt="Entity-relationship diagram where Rental is a weak entity that connects Person and Bike with rental data. Image by author. " class="image--center mx-auto" width="1645" height="273" loading="lazy"></p>
<p>For these examples, let's assume a domain where people rent bicycles. We have a weak entity called <strong>Rental</strong> that models when a person has rented a certain bike, and the attribute <strong>Duration</strong> represents the number of rental days.</p>
<p>As we have seen in previous examples, the primary key of Rental is composed of the rental date and the foreign keys that identify the person who rented a certain bike. This makes Rental weak in identification because both foreign keys are needed to uniquely identify the tuples in that table.</p>
<p>Also, in our domain, we prohibit a person from renting a bike when it’s already being rented by someone else. This means that although everyone can rent as many bikes as they want, they can’t rent one that is already being used by another person or by themselves.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752248300505/daa2d932-d838-4ba4-8f4b-1abaa5f31f98.png" alt="Relational schema diagram where Rental references Bike and Person through foreign keys. Image by author. " class="image--center mx-auto" width="1084" height="469" loading="lazy"></p>
<p>When translating it to the logical level, we simply underline the attributes that are keys and add the foreign key attributes in Rental, as they aren’t represented at the conceptual level. These are underlined because the Rental entity is weak in identification, as we just discussed.</p>
<p>So if we want to implement this logical design in a DBMS like PostgreSQL, we first need to <strong>install</strong> and <strong>configure</strong> it on a machine. Then, once we’ve opened it in a terminal, we can navigate it with different commands (keep in mind that, with the exception of <code>SQL CODE;</code>, these are psql meta-commands (client shortcuts), not SQL.):</p>
<ul>
<li><p><code>\?</code> Shows help about the DBMS commands.</p>
</li>
<li><p><code>\! [command]</code> Executes an operating system terminal command.</p>
</li>
<li><p><code>\h [command]</code> Shows help about the SQL syntax, that is, its statements like <code>\h CREATE TABLE</code>.</p>
</li>
<li><p><code>\q</code> Closes the DBMS, which can also be done with <code>exit</code>.</p>
</li>
<li><p><code>\l</code> or <code>\list</code> Lists all available databases.</p>
</li>
<li><p><code>\c &lt;databaseName&gt;</code> or <code>\connect &lt;databaseName&gt;</code> Connects to the database with the given name.</p>
</li>
<li><p><code>\conninfo</code> Shows information about the current database connection (host, port, user, database).</p>
</li>
<li><p><code>\dn</code> Lists all schemas, which are groupings of elements like tables, views, types, and so on.</p>
</li>
<li><p><code>\dt</code> Shows the tables of the database we are connected to.</p>
</li>
<li><p><code>\dv</code> Similar to the previous command, this one shows the views.</p>
</li>
<li><p><code>\di</code> Lists the indexes.</p>
</li>
<li><p><code>\df</code> Lists the functions.</p>
</li>
<li><p><code>\d[+] object</code> Describes the object whose name we provide as an input argument (table, view, function, and so on). With <code>+</code> it includes additional details.</p>
</li>
<li><p><code>SQL CODE;</code> In the terminal, we can execute SQL code, typically ending with a semicolon.</p>
</li>
<li><p><code>\timing</code> Used to turn on/off the measurement of query execution time.</p>
</li>
<li><p><code>\copy table TO 'file.csv' CSV HEADER;</code> Exports <code>table</code> to a CSV file.</p>
</li>
<li><p><code>\copy table FROM 'file.csv' CSV HEADER;</code> Imports data from a CSV file into a table without emptying it first.</p>
</li>
<li><p><code>\i path/file.sql</code> Executes an SQL script saved in a file with a .sql extension to avoid having to copy and paste lengthy SQL code into the terminal.</p>
</li>
</ul>
<p>When you’re using a DBMS, you should check its documentation to see if it’s case sensitive or not. In this case, <a target="_blank" href="https://stackoverflow.com/questions/21796446/postgres-case-sensitivity">PostgreSQL</a> folds unquoted identifiers to lower-case. Quoted identifiers preserve case and must be matched exactly. SQL keywords aren’t case-sensitive.</p>
<h4 id="heading-create">CREATE</h4>
<p>Once we have entered the DBMS, the first thing we can do is create elements using the CREATE statement. There are many elements we can create, but the most important one for now is DATABASE, which allows us to create a new database.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">DATABASE</span> sampledb;
</code></pre>
<p>If we enter this command directly into the terminal, we will create an empty database that we can connect to using the previous PostgreSQL commands. Once we are in the database, we can create the tables of our logical design with the following:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">INT</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    Birth <span class="hljs-type">DATE</span>,
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>)
);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Bike (
    BikeID <span class="hljs-type">INT</span>,
    Model <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    Weight <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span>
);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Rental (
    PersonFK <span class="hljs-type">INT</span>,
    BikeFK <span class="hljs-type">INT</span>,
    RentalDate <span class="hljs-type">DATE</span>,
    Duration <span class="hljs-type">INT</span>,
    Price <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span>
); <span class="hljs-comment">--Important, don't forget the ; after each statement--</span>
</code></pre>
<p>As you can see, when creating tables, you need to specify the schema for each one. Don’t confuse this with what PostgreSQL calls a schema at the DBMS level. In PostgreSQL, a <strong>schema</strong> is a <strong>namespace</strong> within the database that groups and isolates elements like <strong>tables</strong>, views, functions, and so on. This makes it easier to organize, manage, and control permissions, and avoid name conflicts.</p>
<p>Here, the <strong>table schema</strong> refers to the <strong>attributes</strong> that define it, which is why we declare their names along with their data types, including:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Data Type</strong></td><td><strong>Category</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>BIT</code></td><td>Bit String</td><td>Fixed-size bit string (for example, <code>BIT(1)</code> stores a single 0 or 1).</td></tr>
<tr>
<td><code>SMALLINT</code></td><td>Exact Numeric</td><td>Integer typically from –32,768 to 32,767 (2 bytes).</td></tr>
<tr>
<td><code>INTEGER</code> / <code>INT</code></td><td>Exact Numeric</td><td>Integer typically from –2,147,483,648 to 2,147,483,647 (4 bytes).</td></tr>
<tr>
<td><code>BIGINT</code></td><td>Exact Numeric</td><td>Integer typically from –9,223,372,036,854,775,808 to 9,223,372,036,854,775,807 (8 bytes).</td></tr>
<tr>
<td><code>DECIMAL(p, s)</code></td><td>Exact Numeric</td><td>Fixed-point number with precision <code>p</code> and scale <code>s</code> (for example, money).</td></tr>
<tr>
<td><code>NUMERIC(p, s)</code></td><td>Exact Numeric</td><td>Synonym for <code>DECIMAL</code>, same fixed-point behavior.</td></tr>
<tr>
<td><code>FLOAT(p)</code></td><td>Approximate Numeric</td><td>Floating-point with precision of at least <code>p</code> bits.</td></tr>
<tr>
<td><code>REAL</code></td><td>Approximate Numeric</td><td>Single-precision (typically 24-bit) floating-point.</td></tr>
<tr>
<td><code>DOUBLE PRECISION</code></td><td>Approximate Numeric</td><td>Double-precision (typically 53-bit) floating-point.</td></tr>
<tr>
<td><code>CHAR(n)</code></td><td>Character String</td><td>Fixed-length text of exactly <code>n</code> characters (padded if shorter).</td></tr>
<tr>
<td><code>VARCHAR(n)</code></td><td>Character String</td><td>Variable-length text up to <code>n</code> characters (no padding).</td></tr>
<tr>
<td><code>CLOB</code></td><td>Character String</td><td>Character Large Object for very long text (for example, articles).</td></tr>
<tr>
<td><code>BINARY(n)</code></td><td>Binary String</td><td>Fixed-length binary data of exactly <code>n</code> bytes.</td></tr>
<tr>
<td><code>VARBINARY(n)</code></td><td>Binary String</td><td>Variable-length binary data up to <code>n</code> bytes.</td></tr>
<tr>
<td><code>BLOB</code></td><td>Binary String</td><td>Binary Large Object for large binary data (for example, images).</td></tr>
<tr>
<td><code>DATE</code></td><td>Date/Time</td><td>Calendar date in <code>YYYY-MM-DD</code> format.</td></tr>
<tr>
<td><code>TIME(p)</code></td><td>Date/Time</td><td>Time of day <code>HH:MM:SS[.fraction]</code> with <code>p</code> fractional seconds.</td></tr>
<tr>
<td><code>TIMESTAMP(p)</code></td><td>Date/Time</td><td>Combined date and time with fractional seconds precision <code>p</code>.</td></tr>
<tr>
<td><code>INTERVAL</code></td><td>Date/Time</td><td>Period of time (for example, <code>INTERVAL '1-2' YEAR TO MONTH</code>).</td></tr>
<tr>
<td><code>BOOLEAN</code></td><td>Boolean</td><td>Logical value <code>TRUE</code>, <code>FALSE</code>, or <code>UNKNOWN</code> (NULL).</td></tr>
<tr>
<td><code>XML</code></td><td>Other Standard</td><td>Stores XML document or fragment.</td></tr>
<tr>
<td><code>JSON</code></td><td>Other Standard</td><td>Stores JSON-formatted text for semi-structured data.</td></tr>
<tr>
<td><code>UUID</code></td><td>Other Standard</td><td>128-bit universally unique identifier (for example, <code>550e8400-e29b-41d4-a716-446655440000</code>).</td></tr>
</tbody>
</table>
</div><p>In this list, we can see some like <strong>BLOB</strong> that at first glance allow storing an arbitrary amount of data in a single cell, as the BLOB can be as large as we want. This might seem like it poses a repetitive group problem. But when a column stores BLOB data, it doesn't store multiple BLOBs in the same cell, but only one. This makes the DBMS responsible for managing the disk storage of this type of data efficiently.</p>
<p>In other words, we can see this as if the BLOB itself is not stored in a table cell, but rather a memory pointer is stored pointing to another memory area where the entire BLOB is stored (although the exact technique used heavily depends on the DBMS).</p>
<p>Also, if we look at other data types like <strong>VARCHAR</strong> for storing text, in PostgreSQL you can use VARCHAR with or without a length (or TEXT). In standard SQL, VARCHAR(n) requires a length.</p>
<p>Besides creating databases and tables, we might want to create a custom data type like <strong>ageDataType</strong> or <strong>colorDataType</strong>, which we can do using <strong>CREATE DOMAIN</strong>.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">DOMAIN</span> ageDataType <span class="hljs-keyword">AS</span> <span class="hljs-type">INTEGER</span> <span class="hljs-keyword">CHECK</span> (<span class="hljs-keyword">VALUE</span> &gt;= <span class="hljs-number">0</span> <span class="hljs-keyword">AND</span> <span class="hljs-keyword">VALUE</span> &lt;= <span class="hljs-number">150</span>);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">DOMAIN</span> colorDataType <span class="hljs-keyword">AS</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">8</span>) <span class="hljs-keyword">CHECK</span> (<span class="hljs-keyword">VALUE</span> <span class="hljs-keyword">IN</span> (<span class="hljs-string">'red'</span>, <span class="hljs-string">'green'</span>, <span class="hljs-string">'BlUe'</span>));
</code></pre>
<p>Here we just created new data types called ageDataType and colorDataType, where the first one is used to represent ages and the other colors. We could do this by imposing constraints on the values that columns can take, rather than defining a new data type, or rather a domain. But if there are many attributes with the same constraints on their domain, meaning they have the same domain like color or age, then it makes sense to define a custom one.</p>
<p>We mainly do this using the CHECK statement, which as we'll see is used to define constraints (in this case on the values of the data type we define as a base when creating a new domain. Above we used INTEGER and VARCHAR(8) respectively.).</p>
<h4 id="heading-alter">ALTER</h4>
<p>In addition to creating elements like tables or databases, we can also modify them using the <strong>ALTER</strong> statement. For example, if we forgot to add the <strong>AuxEmail</strong> column to the <strong>Person</strong> table, we can use the following statement to add it after the table has been created.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> Person
  <span class="hljs-keyword">ADD</span> <span class="hljs-keyword">COLUMN</span> AuxEmail <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>);
</code></pre>
<p>As you can see, we first specify the table where we want to add the new column, and then we specify the name and type of that attribute. But it's important to consider the value assigned to its cells when this table extension occurs.</p>
<p>By default, SQL <strong>allows NULL values</strong> in the table, so it will fill those values with <strong>NULL</strong> if there is content in the table. But if we want to assign a custom default value to the cells of the new column instead of NULL when there is data already inserted in the table, we can add the default value property to the column we are adding:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> Person
  <span class="hljs-keyword">ADD</span> <span class="hljs-keyword">COLUMN</span> AuxEmail <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">'noEmail@gmail.com'</span>;
</code></pre>
<p>This way, when we insert a tuple and leave the <strong>AuxEmail</strong> value undefined, the DBMS will automatically fill the cell for that attribute with its default value. This also applies when adding the column itself when there is already data in the table. We can also remove this default value property using:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> Person
  <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">COLUMN</span> Email <span class="hljs-keyword">DROP</span> <span class="hljs-keyword">DEFAULT</span>;
</code></pre>
<p>Similarly, ALTER also allows us to remove an attribute:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> Person
  <span class="hljs-keyword">DROP</span> <span class="hljs-keyword">COLUMN</span> Email;
</code></pre>
<p>Change the data type of an attribute in Postgres:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> Person
  <span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">COLUMN</span> <span class="hljs-type">Name</span> <span class="hljs-keyword">TYPE</span> <span class="hljs-type">CHAR</span>(<span class="hljs-number">25</span>);
</code></pre>
<p>And rename elements, among many other actions:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> Person
  <span class="hljs-keyword">RENAME</span> <span class="hljs-keyword">COLUMN</span> Birth <span class="hljs-keyword">TO</span> BirthDate; <span class="hljs-comment">--Renames the column Birth of the table Person--</span>
<span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">TABLE</span> Person
  <span class="hljs-keyword">RENAME</span> <span class="hljs-keyword">TO</span> People; <span class="hljs-comment">--Renames the table Person--</span>
<span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">DATABASE</span> sampledb
  <span class="hljs-keyword">RENAME</span> <span class="hljs-keyword">TO</span> otherName; <span class="hljs-comment">--Renames the database sampledb--</span>
</code></pre>
<p>In short, ALTER allows us to modify elements that have already been created in the database without deleting and recreating them with the changes. Otherwise, we would have to export the data stored in those elements and reinsert it into the new schemas, which would be inefficient.</p>
<h4 id="heading-drop">DROP</h4>
<p>We can remove elements with the DROP statement. Its operation is very simple, as we just need to specify the name of the element to remove, such as the database we just created:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">DATABASE</span> sampledb;
</code></pre>
<p>When executing this statement, SQL tries to delete the database, although we might get an error if we are connected to it. Besides simply deleting it, we can check if it exists before trying to delete it with:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">DATABASE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> sampledb;
</code></pre>
<p>Similarly, we can have a schema like this example where there are foreign keys in Rental that reference or point to other tables like Bike and Person.</p>
<p>If we delete Rental, nothing would happen since no foreign key points to Rental. But if we want to delete one of the other two tables, a referential integrity problem will arise. For example, deleting Bike would leave the foreign key reference in Rental that points to Bike orphaned. So to delete Bike and all the constraints or SQL elements that depend on Bike, meaning those that reference it, we can use CASCADE:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> Bike <span class="hljs-keyword">CASCADE</span>;
</code></pre>
<p>By doing this, not only would Bike be deleted, but also the foreign key constraint in Rental that we haven't introduced yet, as well as all others that point to Bike.</p>
<p>It's important to note that the CASCADE in a DROP statement is not related to the CASCADE we can define in a CREATE statement to set deletion or insertion policies. If, instead of deleting an entire table, we only delete certain tuples, we might end up with a situation where a tuple has a foreign key value that doesn't correspond to any tuple in the referenced table because we deleted it. We can establish deletion policies where the tuples pointing to the deleted one are also removed, or similar actions.</p>
<h4 id="heading-insert">INSERT</h4>
<p>To insert tuples into tables, we use the INSERT statement, where we specify the name of the table where we want to insert, as well as the attributes of its schema and the values to insert into the new tuple.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> Person (PersonID, <span class="hljs-type">Name</span>, Birth, Email)
<span class="hljs-keyword">VALUES</span> (<span class="hljs-number">5</span>, <span class="hljs-string">'Carol Johnson'</span>, <span class="hljs-string">'1985-07-15'</span>, <span class="hljs-string">'carol@example.com'</span>);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> Bike (BikeID, Model, Weight)
<span class="hljs-keyword">VALUES</span> (<span class="hljs-number">5</span>, <span class="hljs-string">'EcoCruiser'</span>, <span class="hljs-number">14.2</span>);

<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> Rental (PersonFK, BikeFK, RentalDate, Duration, Price)
<span class="hljs-keyword">VALUES</span> (<span class="hljs-number">5</span>, <span class="hljs-number">5</span>, <span class="hljs-string">'2025-07-10'</span>, <span class="hljs-number">3</span>, <span class="hljs-number">25.50</span>);
</code></pre>
<p>But, if we don't have some of the values for the tuple, we can omit them by inserting values only for the attributes we do have. We can even insert a tuple with DEFAULT values for certain attributes. But this only works if a default value was defined when creating the table or added with an ALTER statement.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> Bike (BikeID, Model)
<span class="hljs-keyword">VALUES</span> (<span class="hljs-number">6</span>, <span class="hljs-string">'Speedster'</span>);
<span class="hljs-keyword">INSERT</span> <span class="hljs-keyword">INTO</span> Bike (BikeID, Model, Weight)
<span class="hljs-keyword">VALUES</span> (<span class="hljs-number">7</span>, <span class="hljs-string">'Commuter'</span>, <span class="hljs-keyword">DEFAULT</span>);
</code></pre>
<h4 id="heading-delete">DELETE</h4>
<p>To delete tuples, you can use DELETE, which at a logical level is very similar to the SELECT clause that we will see later (that’s used to retrieve data in response to database queries).</p>
<p>To use DELETE, we impose a set of conditions that the tuples in the table must meet to be selected. Those tuples that meet the conditions are then deleted by DELETE.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">FROM</span> Rental
<span class="hljs-keyword">WHERE</span> PersonFK = <span class="hljs-number">5</span>
  <span class="hljs-keyword">AND</span> BikeFK   = <span class="hljs-number">5</span>
  <span class="hljs-keyword">AND</span> RentalDate = <span class="hljs-string">'2025-07-10'</span>;
</code></pre>
<p>For example, here all tuples with a value of 5 in PersonFK and BikeFK and a rental date of 2025-07-10 will be deleted.</p>
<h4 id="heading-update">UPDATE</h4>
<p>Similarly, we can update the values of tuples using UPDATE. We first select the tuples that will be affected by the change we want to make by imposing conditions on them, and then we use SET to change one of their attribute values or apply a transformation.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">UPDATE</span> Bike
<span class="hljs-keyword">SET</span> Weight = <span class="hljs-number">13.8</span>
<span class="hljs-keyword">WHERE</span> BikeID = <span class="hljs-number">5</span>;

<span class="hljs-keyword">UPDATE</span> Person
<span class="hljs-keyword">SET</span> Email = <span class="hljs-string">'carol.johnson@example.com'</span>
<span class="hljs-keyword">WHERE</span> PersonID = <span class="hljs-number">5</span>;
</code></pre>
<h4 id="heading-constraints-implementation">Constraints implementation</h4>
<p>Given these <strong>DDL</strong> statements, we can create different elements where data is stored. But as we’ve seen, in most domains we model, we need to implement a series of constraints to ensure that the data adheres to the requirements of our problem. (This is in addition to the integrity constraints inherent in the relational model, such as the existence of keys.)</p>
<p>Although this distinction is not as strong in SQL, most constraints we impose help ensure data integrity, whether they refer to the relational model's own rules or the business rules of our problem.</p>
<p>To implement constraints in SQL, we can start with the simplest ones: constraints that affect a single table. These are usually implemented using the <strong>CHECK</strong> statement within another statement like <strong>CREATE TABLE</strong>, where a condition is specified that all tuples in a table must meet whenever we modify it by inserting, modifying, or deleting its tuples.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">INT</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    Birth <span class="hljs-type">DATE</span>,
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    <span class="hljs-keyword">CHECK</span> (Birth &lt;= <span class="hljs-built_in">CURRENT_DATE</span>)
);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">INT</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    Birth <span class="hljs-type">DATE</span>,
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    <span class="hljs-keyword">CONSTRAINT</span> BirthConstraint <span class="hljs-keyword">CHECK</span> (Birth &lt;= <span class="hljs-built_in">CURRENT_DATE</span>)
);
</code></pre>
<p>For example, we can assume that a person's birth date is always validated before being saved in the database. If a user enters an invalid date in the application layer, the application itself will generate an error and prevent saving an invalid date in the database. But it's still a good idea to add this type of constraint to ensure data integrity.</p>
<p>In this case, a person can’t be born on a date later than the current date, which we can get in SQL with <strong>CURRENT_DATE</strong>. So, we define a constraint where the <strong>Birth</strong> attribute must be less than or equal to the current date for all rows in the Person table.</p>
<p>These constraints are usually defined below the attribute declaration, and we can also give them a specific name using <strong>CONSTRAINT</strong>. This declares the constraint and assigns it a name we can use to identify it. We can add this name not only to a CHECK constraint but also to any similar declaration, such as <strong>PRIMARY KEY</strong>, <strong>FOREIGN KEY</strong>, or <strong>UNIQUE</strong>, among others.</p>
<p>Continuing with constraints on a specific table, if we need to ensure that an attribute can’t take NULL values, we can use either a CHECK or a NOT NULL along with declaring the corresponding attribute (to which we can also give a specific name using CONSTRAINT).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">INT</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    Birth <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>)
);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">INT</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    Birth <span class="hljs-type">DATE</span> <span class="hljs-keyword">CONSTRAINT</span> BirthNotNull <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>)
);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">INT</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    Birth <span class="hljs-type">DATE</span>,
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    <span class="hljs-keyword">CONSTRAINT</span> BirthNotNull <span class="hljs-keyword">CHECK</span> (Birth <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>)
);
</code></pre>
<p>These three ways are equivalent if we want to require people to save their birth date in the database, preventing NULL values in the respective column.</p>
<p>The main difference between using CHECK and putting NOT NULL next to the attribute declaration is that if we use CHECK, we have to write a condition in parentheses similar to how we do it in a SQL query that describes the condition we want to impose, as long as this query only affects the attributes of the table we are working on.</p>
<p>In contrast, NOT NULL next to an attribute is an implicit way to indicate this restriction. Note that CHECK constraints are per-row boolean expressions – they can’t contain subqueries, aggregates, or window functions in standard SQL and most DBMS. For cross-table conditions, use <strong>triggers</strong> (portable) rather than CHECK.</p>
<p>After understanding what CHECK involves, we can see how almost any domain restriction on attributes can be specified in one of these statements. However, SQL offers us more functionalities, such as setting a default value for attributes with <strong>DEFAULT</strong>.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">INT</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">'No name'</span>,
    Birth <span class="hljs-type">DATE</span>,
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>)
);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">INT</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">CONSTRAINT</span> NameDefaultValue <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">'No name'</span>, <span class="hljs-comment">--We can name the default value too--</span>
    Birth <span class="hljs-type">DATE</span>,
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>)
);
</code></pre>
<p>As we’ve seen before, we use <strong>DEFAULT</strong> so that when a tuple is inserted with a missing value for a certain attribute, if that attribute has a default value defined, the tuple will be inserted with that default value in the corresponding attribute instead of <strong>NULL</strong>.</p>
<p>This is important because if we include the NOT NULL restriction and don’t define a default value for an attribute, the DBMS may generate an error here. This also applies when a new attribute is added to the table using ALTER, where we can define a default value at the same time.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Bike (
    BikeID <span class="hljs-type">INT</span>,
    Model <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    Weight <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span>,
    <span class="hljs-keyword">CONSTRAINT</span> ModelValues <span class="hljs-keyword">CHECK</span> (Model <span class="hljs-keyword">IN</span> (<span class="hljs-string">'Model1'</span>, <span class="hljs-string">'Model2'</span>, <span class="hljs-string">'Model3'</span>))
);
</code></pre>
<p>As a curiosity, if we want to explicitly define the possible values an attribute can take, we can use a CHECK like the one above. This is the same expression we use when creating a new domain with <strong>CREATE DOMAIN</strong>. We can then assign it as the data type to the Model attribute. So we have the option to create a custom domain for an attribute or define a constraint with CHECK to model its domain (although in most cases, it's better to use <strong>CREATE DOMAIN</strong> for better maintainability).</p>
<p>Continuing with constraints that affect a single table, we also have those more related to data integrity concerning the relational model. For example, to uniquely identify the tuples of a table, we have candidate keys in the relational model, which we can declare in SQL using <strong>UNIQUE</strong> in combination with NOT NULL.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Bike (
    BikeID <span class="hljs-type">INT</span>,
    Model <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">255</span>),
    Weight <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span>,
    <span class="hljs-keyword">UNIQUE</span> (Model)
);
</code></pre>
<p>For example, if we assume that in our problem there aren't multiple different bikes with the same model name, then we can use Model as a candidate key to uniquely identify all the tuples in the table.</p>
<p>So to explicitly declare that Model can serve for tuple identification, we use UNIQUE. This indicates that all the values that this attribute takes in (all the tuples of the table) must be different.</p>
<p>We can also apply this to more than one attribute, where UNIQUE would determine that the combination of values of all those attributes included in the constraint must be different in all the tuples of the table.</p>
<p>The main usefulness of UNIQUE is that it ensures certain attributes meet the definition of a candidate key. So, if we insert multiple tuples with the same repeated values in attributes that form a candidate key defined with UNIQUE, the DBMS will generate an error. But beyond this, we don’t have to define all candidate keys that exist unless the domain or problem requirements force us to do so.</p>
<p>Usually, we’d just define the primary key of a table with PRIMARY KEY, without needing it to be a selected candidate key.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-built_in">INT</span>,
    <span class="hljs-keyword">Name</span> <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>) <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">'No name'</span>,
    Birth <span class="hljs-built_in">DATE</span>,
    Email <span class="hljs-built_in">VARCHAR</span>(<span class="hljs-number">255</span>),
    <span class="hljs-keyword">CONSTRAINT</span> PersonPK PRIMARY <span class="hljs-keyword">KEY</span> (PersonID) <span class="hljs-comment">--The constraint is named PersonPK--</span>
);
</code></pre>
<p>When we introduce the primary key constraint on a set of attributes, we are implicitly declaring that these attributes can’t contain NULL values, and the combinations of values they take must all be unique in the table's tuples (just like with UNIQUE).</p>
<p>It’s as if we’re implicitly defining UNIQUE and NOT NULL on the attributes that form the primary key, making sure that they meet all the necessary conditions to truly form a primary key (which can also be referenced by a foreign key).</p>
<p>To declare the existence of foreign keys, we use FOREIGN KEY on the attributes that constitute it.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Rental (
    PersonFK <span class="hljs-type">INT</span>,
    BikeFK <span class="hljs-type">INT</span>,
    RentalDate <span class="hljs-type">DATE</span>,
    Duration <span class="hljs-type">INT</span>,
    Price <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span>,
    <span class="hljs-keyword">CONSTRAINT</span> RentalPK <span class="hljs-keyword">PRIMARY KEY</span> (PersonFK, BikeFK, RentalDate),
    <span class="hljs-keyword">CONSTRAINT</span> FK_Rental_Person <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID) <span class="hljs-keyword">ON</span> <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">CASCADE</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">CASCADE</span>,
    <span class="hljs-keyword">CONSTRAINT</span> FK_Rental_Bike <span class="hljs-keyword">FOREIGN KEY</span> (BikeFK) <span class="hljs-keyword">REFERENCES</span> Bike(BikeID) <span class="hljs-keyword">ON</span> <span class="hljs-keyword">DELETE</span>
    <span class="hljs-keyword">SET</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">CASCADE</span>
);
</code></pre>
<p>As you can see, declaring foreign keys is very similar to primary keys, except that we. usethe FOREIGN KEY statement. But for the DBMS to ensure referential integrity in the database, we need to define what happens when inserting, updating, or deleting tuples from tables that are referenced by foreign keys.</p>
<p>To understand this, the simplest case is when a tuple is inserted into a table like Rental, where values must be provided for its foreign keys. By default (NO ACTION), SQL allows a foreign key to take NULL values, meaning NULL satisfies the foreign key constraint. But in this case, we should add a NOT NULL constraint on these attributes because, in the conceptual model, a Rental entity was related to at least one Bike entity and one Person entity, as indicated by the minimum cardinality.</p>
<p>So if we insert a tuple with a NULL value in the foreign key attribute and we had the NOT NULL constraint, we’d receive an error. On the other hand, if we insert a value that is not NULL but doesn’t exist in the attribute of the table we are referencing, then the DBMS won’t allow that insertion either – as that foreign key won’t be referencing an existing tuple in the table it points to.</p>
<p>To indicate where it points, we use REFERENCES in the FOREIGN KEY constraint itself, where the table and the attribute the foreign key should point to are specified. A foreign key must reference a candidate key in the parent table—either the primary key or another column (or column set) declared UNIQUE and NOT NULL. The referencing and referenced columns must match in number, order, and compatible data types.</p>
<p>Afterward, if we try to delete a tuple from the Bike or Person table that is referenced by a tuple in the Rental table, we can set several deletion policies.</p>
<p>First, by deleting the tuple from Bike or Person, we would have a tuple in Rental that does not reference any valid tuple from another table, creating a referential integrity problem due to an orphaned reference.</p>
<p>One option to solve this is to also delete the tuple in the Rental table and recursively delete the tuples that point to the tuples being removed by this process. We declare this with ON DELETE CASCADE. But if we want to keep the tuple in Rental, instead of deleting it, we can assign a particular value to the foreign key that no longer points to any valid tuple (such as NULL or the default value DEFAULT). We declare this with <strong>ON DELETE SET [value]</strong>, where [value] can be SET NULL or SET DEFAULT.</p>
<p>But we need to be careful with NULL, because if the foreign key attribute is also part of the primary key, as in this example, it will conflict with the implicit PRIMARY KEY constraint that prevents it from being NULL.</p>
<p>We aren’t required to declare ON DELETE in these constraints, so if we don't, the default action (called NO ACTION) will be executed. This means rejecting the deletion of the tuple in Bike or Person, and showing an error to the user.</p>
<p>Similarly, this issue can also occur when updating a tuple, so the same ON DELETE mechanism applies to tuple modifications, which we can define with ON UPDATE.</p>
<p>Finally, a foreign key can reference the same table it’s in, and using the CASCADE policy is completely valid. This is because it recursively deletes tuples that cause referential integrity issues, not entire tables. Even if there are tuples that reference themselves, this poses no problem, as the DBMS can handle these edge cases.</p>
<p>These are the basic constraints that we can apply to a single table, although there are more advanced tools that help ensure data integrity or even optimize its manipulation and querying.</p>
<p>But there are some constraints that don’t only affect one table in the schema but can involve conditions on multiple tables. To implement them, we have several options, such as assertions, which are conditions very similar to CHECK that are verified every time any of the tables involved in the condition are modified.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">ASSERTION</span> RentalEmailConstraint <span class="hljs-keyword">CHECK</span> (
    <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> <span class="hljs-number">1</span>
        <span class="hljs-keyword">FROM</span> Rental r
            <span class="hljs-keyword">JOIN</span> Person p <span class="hljs-keyword">ON</span> r.PersonFK = p.PersonID
        <span class="hljs-keyword">WHERE</span> p.Email <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
    )
);
</code></pre>
<p>For example, here we create an assertion that checks we haven’t rented a bike to any person who doesn't have an Email defined. For this type of constraint, we usually use complete SQL queries within the CHECK, as they are more complex to model than the CHECK constraints we place on a single table.</p>
<p>We could also do this in the table CHECK constraints instead of using assertions, although it would often be more complex to model.</p>
<p>Lastly, besides assertions, we can implement constraints on multiple tables with triggers, which are statements composed of an event, a condition, and an action. When the defined event occurs, the condition that constitutes the constraint is checked, and depending on whether it’s true or false, a certain action is executed or not on the database.</p>
<p>Now that we know how to set constraints on a relational schema, we can refine the logical implementation of our example by adding the necessary constraints, resulting in the following code:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> Rental;
<span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> Bike;
<span class="hljs-keyword">DROP</span> <span class="hljs-keyword">TABLE</span> <span class="hljs-keyword">IF</span> <span class="hljs-keyword">EXISTS</span> Person;
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">50</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">DEFAULT</span> <span class="hljs-string">'No name'</span>,
    Birth <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">50</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">UNIQUE</span>,
    <span class="hljs-keyword">CONSTRAINT</span> PersonPK <span class="hljs-keyword">PRIMARY KEY</span> (PersonID),
    <span class="hljs-keyword">CONSTRAINT</span> ConstraintPersonBirth <span class="hljs-keyword">CHECK</span> (Birth &lt;= <span class="hljs-built_in">CURRENT_DATE</span>)
);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Bike (
    BikeID <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Model <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">50</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Weight <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-comment">--This constraint is redundant due to the definition of PRIMARY KEY constraint--</span>
    <span class="hljs-keyword">UNIQUE</span> (BikeID),
    <span class="hljs-keyword">CONSTRAINT</span> BikePK <span class="hljs-keyword">PRIMARY KEY</span> (BikeID),
    <span class="hljs-keyword">CONSTRAINT</span> ConstraintBikeWeight <span class="hljs-keyword">CHECK</span> (Weight &gt; <span class="hljs-number">0</span>) <span class="hljs-comment">--Weight must be positive--</span>
);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Rental (
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    BikeFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    RentalDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Duration <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Price <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">CONSTRAINT</span> RentalPK <span class="hljs-keyword">PRIMARY KEY</span> (PersonFK, BikeFK, RentalDate),
    <span class="hljs-keyword">CONSTRAINT</span> FKRentalPerson <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID) <span class="hljs-keyword">ON</span> <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">CASCADE</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">CASCADE</span>,
    <span class="hljs-keyword">CONSTRAINT</span> FKRentalBike <span class="hljs-keyword">FOREIGN KEY</span> (BikeFK) <span class="hljs-keyword">REFERENCES</span> Bike(BikeID) <span class="hljs-keyword">ON</span> <span class="hljs-keyword">DELETE</span> <span class="hljs-keyword">CASCADE</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">UPDATE</span> <span class="hljs-keyword">CASCADE</span>,
    <span class="hljs-keyword">CONSTRAINT</span> ConstraintRentalDuration <span class="hljs-keyword">CHECK</span> (Duration &gt; <span class="hljs-number">0</span>),
    <span class="hljs-keyword">CONSTRAINT</span> ConstraintRentalPrice <span class="hljs-keyword">CHECK</span> (Price &gt;= <span class="hljs-number">0</span>),
    <span class="hljs-keyword">CONSTRAINT</span> ConstraintRentalDate <span class="hljs-keyword">CHECK</span> (RentalDate &lt;= <span class="hljs-built_in">CURRENT_DATE</span>)
);
</code></pre>
<p>As you can see, in the creation script, we have added some DROP statements to remove the tables before creating the final ones with all the correct constraints. We usually do this when there is no data in the tables, as a DROP would delete everything stored in them. Also, when we delete several tables that are related through foreign keys, we want to avoid the DBMS generating referential integrity errors. Because of this, it’s common to first delete the tables that do not have any foreign keys pointing to them, and then continue with the rest.</p>
<h3 id="heading-dcl">DCL</h3>
<p>Now that you’ve seen how to define the basic elements of the relational model in a DBMS with SQL, we should consider the security with which these operations are performed (as well as those we’ll see in DML). After all, not all database users may have good intentions when operating on the DBMS.</p>
<p>So in DCL, we can define a series of statements for managing users, roles, and permissions, which establish who can do what on the database.</p>
<h4 id="heading-user-roles">User roles</h4>
<p>The first thing we can do is create <strong>roles</strong>, which, as the name suggests, is a role assigned to a database user that determines what they can or can’t do with the database. Basically, the role functions as a <strong>set of permissions</strong>.</p>
<p>By default, a PostgreSQL role can’t log in unless it’s created WITH LOGIN (or via CREATE USER). So to simplify this section, we can assume that when a user wants access to the database, it’s enough to give them a role with login permission (although these mechanisms may depend on the DBMS we are using).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">ROLE</span> user1 <span class="hljs-keyword">WITH</span> <span class="hljs-keyword">LOGIN</span> <span class="hljs-keyword">PASSWORD</span> <span class="hljs-string">'userPassword'</span>;
<span class="hljs-keyword">DROP</span> <span class="hljs-keyword">ROLE</span> user1; <span class="hljs-comment">--If we want to remove the role--</span>
</code></pre>
<p>So it can authenticate to the DBMS using the password we define here. In PostgreSQL, roles can typically connect by default because CONNECT is granted to PUBLIC. To restrict access you first REVOKE CONNECT ON DATABASE ... FROM PUBLIC and then GRANT CONNECT selectively. So, updating permissions with GRANT:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">CONNECT</span> <span class="hljs-keyword">ON</span> <span class="hljs-keyword">DATABASE</span> sampledb <span class="hljs-keyword">TO</span> user1;
</code></pre>
<p>By default, the user won't be able to do anything else other than connect. So by using GRANT in the following way, we can give the necessary permissions to execute any necessary statements on certain elements of the database.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">SELECT</span>, <span class="hljs-keyword">UPDATE</span>
<span class="hljs-keyword">ON</span> <span class="hljs-keyword">TABLE</span> Rental
<span class="hljs-keyword">TO</span> user1;
</code></pre>
<p>For example, here we are giving permission to execute the SELECT and UPDATE statements on the Rental table.</p>
<p>Or if we want to give all possible permissions to do anything on an element, we can use ALL, like this:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">ALL</span> <span class="hljs-keyword">PRIVILEGES</span>
<span class="hljs-keyword">ON</span> <span class="hljs-keyword">TABLE</span> Bike
<span class="hljs-keyword">TO</span> user1;
</code></pre>
<p>Or, if we want to be more precise, we can even control which columns of a table certain statements can be executed on:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">GRANT</span> <span class="hljs-keyword">SELECT</span> (PersonID, <span class="hljs-type">Name</span>)
<span class="hljs-keyword">ON</span> <span class="hljs-keyword">TABLE</span> Person
<span class="hljs-keyword">TO</span> user1;
</code></pre>
<p>Similarly, if instead of using GRANT we use REVOKE, we remove certain permissions that the role has:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">REVOKE</span> <span class="hljs-keyword">ALL</span> <span class="hljs-keyword">PRIVILEGES</span>
<span class="hljs-keyword">ON</span> <span class="hljs-keyword">TABLE</span> Bike
<span class="hljs-keyword">FROM</span> user1;
</code></pre>
<p>This is just a part of what can be controlled for a role in a database using DCL statements, as security is a critical aspect.</p>
<h3 id="heading-dml">DML</h3>
<p>After setting up user permissions to control what a user can do in the database, we have enough elements to start manipulating and querying the data. So now it’s time to introduce the set of statements that make up the DML of SQL, which mainly handles the management of stored data.</p>
<h4 id="heading-crud">CRUD</h4>
<p>To understand data management, you should think about how you’ll operate on them. This is guided by the needs of the user or end client. From this arises the <strong>CRUD pattern (Create, Retrieve, Update, and Delete)</strong>, which defines the fundamental operations performed on the data of a real project and that the database must support.</p>
<p>As you can see from its acronym, at the most fundamental level in our database, new data can be inserted (Create), queried once stored (Retrieve), and can also be modified (Update) or deleted (Delete) when they are no longer useful for the domain.</p>
<p>Of all these operations, the most important one is querying the data. If we think about it, any service provided to the end user can be reduced to a query on stored data.</p>
<p>For example, simply viewing saved information means it has to be retrieved through a query. Really any metric that needs to be calculated on the data also involves querying and then computing on it. So even though DML involves a wide variety of statements with diverse objectives, we will focus here on those that form the fundamental blocks for performing queries – CRUD.</p>
<p>When working with relational databases, there’s a certain the mechanism that queries follow to obtain the data we request from the DBMS.</p>
<p>First, we have a series of tables where information is stored in tuples. These we will call base tables, meaning the ones we initially create with CREATE TABLE. We don’t modify these base tables directly – instead, we apply a series of operations to them, many from relational algebra, resulting in intermediate tables. These intermediate tables pass through the sequence of operators until we reach a final table with the results we asked for.</p>
<p>In other words, a query consists of obtaining a resulting table with data from a set of base tables.</p>
<p>From a formal perspective, this is sometimes interpreted in relational algebra as if the query were a <a target="_blank" href="https://www.cs.emory.edu/~cheung/Courses/554/Syllabus/5-query-opt/intro.html"><strong>relational tree</strong></a> where the leaf nodes are the base tables. As operators, which can be either unary or binary, are applied, new intermediate tables are generated, representing the intermediate nodes of the tree until reaching the <strong>root node</strong>, which is the final table, or the <strong>query result</strong>.</p>
<p>With this, we can see each operator as if it were a mathematical function that takes one or more tables as input, performs a certain operation on them, and returns another table as output.</p>
<p>In contrast, when we program in SQL, we don't directly use these relational operators, as they are formal tools that support data querying. Instead, we use a series of DML statements, some of which resemble relational operators but are actually meant to be combined with other statements to form a query.</p>
<p>SQL is not a formal language like relational algebra – it’s an implementation based on this formal language, as well as on relational calculus, which allows us to abstract certain formal details. So when we’re executing a SQL query, the DBMS will transform it from a sequence of SQL statements into an execution plan more similar to a sequence of relational algebra operators. Then it’s internally resolved with advanced techniques that work on the formal operators themselves.</p>
<p>It's also important to note that most of the optimization is done by the DBMS when analyzing the structure of the query. Despite this, we should always try to "help" the DBMS optimizer by writing SQL queries that aim to minimize its workload. For this, there are certain <a target="_blank" href="https://www.geeksforgeeks.org/sql/best-practices-for-sql-query-optimizations/"><strong>techniques</strong></a> you should follow (but that we won’t cover in detail here).</p>
<p>Before introducing DML statements, it's a good idea to have the <a target="_blank" href="https://gist.github.com/cardstdani/587e515368c9755ab6bc9b78a119292f"><strong>schema</strong></a> loaded with the Person, Bike, and Rental tables, as well as some sample data. In addition to creating the tables, to ensure that the queries return some data and we can verify they actually work, you’ll need to insert data into them using INSERT.</p>
<h4 id="heading-select-and-from">SELECT and FROM</h4>
<p>The first statements we'll look at for building a query are the most basic ones: SELECT and FROM. You often need a FROM to construct a SQL query, as it’s used to determine from which table the data will be gotten. (Depending on the DBMS, you can run queries without a FROM (for example, <code>SELECT 1;</code>), though some systems use alternatives like <code>VALUES</code> or <code>FROM DUAL</code>.) Here’s how it works:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Bike;
</code></pre>
<p>For example, if we run this query, it will return all the tuples stored in the Bike table. This is because we have provided one table to FROM, in this case, Bike, from which the data will be obtained. (FROM can reference one or more tables (including joins, subqueries, or CTEs)). Then, after getting the data from that table, SELECT * is used to select the data from all its columns, which is what we will return to the user.</p>
<p>Although we can only use one table in the FROM, we can actually perform a series of operations on several base tables and use that result as the table in the FROM. In other words, we can make the result of a SQL query, which is itself a table, the table used in the FROM, as shown here:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> (<span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> Bike);
</code></pre>
<p>This isn’t common to do with such a simple example, but it’s useful to show that we can provide anything we can build with a SQL query as the table to FROM (since the result of all the queries we can construct is actually a table).</p>
<p>When trying to transfer the functionality of these statements to relational algebra operators, we’ll see that there is no specific operator for FROM that does something similar.</p>
<p>But for SELECT there is an operator that does almost the same thing. Specifically, in relational algebra, there is the projection operator <strong>π(Table, ListAttributes)</strong>. It takes as input a table with data and a list of some of its attributes, and returns another table constructed from the input where only the attributes in the list are kept – with all the data from their columns – discarding the rest of the attributes not appearing in the list.</p>
<p>This is exactly what SELECT does: we have an input table given by the FROM clause, and then we define a series of attributes we want the resulting table to have, discarding the rest.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> <span class="hljs-type">Name</span>, Birth
<span class="hljs-keyword">FROM</span> Person;
</code></pre>
<p>For example, when FROM gets the data from the Person table, it provides it as input to SELECT. This then returns a table where only the attributes Name and Birth that we listed are present, with all the data from their columns. If we need to get all the attributes, we can use SELECT *, and we’ll get the input table with all its attributes and data as it was received.</p>
<h4 id="heading-aliases">Aliases</h4>
<p>Another operator that we have in SQL in an almost equivalent form is the <strong>renaming operator</strong>. As its name suggests, we use it to provide alternative names to the tables or attributes we use, to avoid ambiguity problems or to shorten long names.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.Name, Birth <span class="hljs-keyword">AS</span> B
<span class="hljs-keyword">FROM</span> Person P;
</code></pre>
<p>In relational algebra, the operator is denoted as <strong>ρ(Object, Alias)</strong>, and its function is to assign an alias to an object, which can be either a table or an attribute.</p>
<p>In SQL, there are several ways to use it. On one hand, in the FROM clause, we can use AS [alias] or directly place the alias name after the table or tables involved in the query. This lets us refer to them by their alias instead of their full name, especially if we use the same one multiple times.</p>
<p>Also, in the SELECT clause, we should use AS to avoid ambiguities when assigning aliases to the attributes we’re going to return. The main utility here is to rename the returned attributes to have more descriptive or context-appropriate names.</p>
<p>For example, instead of returning the attribute Birth, its data is returned with the name B, which is shorter, while the Name attribute from table P is returned with the same name it has at the time of performing the SELECT.</p>
<h4 id="heading-distinct">DISTINCT</h4>
<p>Another important statement is DISTINCT, which we use to remove duplicate tuples from the query result. To understand this, it's important to note that SQL doesn’t use sets to represent the tuples of a table. Instead, the tuples are represented in a multiset, allowing for identical tuples, especially in intermediate tables where primary key constraints and others don’t apply. So if we want the result to have no duplicate tuples, we need to add DISTINCT at the beginning of the attribute list in the SELECT statement.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">DISTINCT</span> P.Name 
<span class="hljs-keyword">FROM</span> Person P;
</code></pre>
<p>When executing this query, we should see fewer names because some people have the same name. Also, DISTINCT is not only used at the beginning of the attribute list. We can also use it to count or perform aggregation operations that affect only non-repeated values, as we’ll see later.</p>
<p>This statement doesn’t have a direct equivalent with any relational algebra operator, as relational algebra formally works with sets where duplicate tuples do not exist, eliminating the need for a specific operator to remove duplicates.</p>
<h4 id="heading-where">WHERE</h4>
<p>With what we've seen so far, we can retrieve data from tables, even removing duplicates or unnecessary attributes for the result – but we haven't introduced a way to keep only those tuples that meet certain conditions.</p>
<p>This is precisely what the WHERE clause in SQL does, which has a very similar relational algebra operator called the <strong>selection operator</strong> (don’t confuse with SELECT) and denoted as <strong>σ(Table,Condition)</strong>. This operator takes a table with data and a condition applied to the tuples stored in the table, so that only those tuples that meet the condition are considered in the output table provided by the operator.</p>
<p>In other words, all operators output a resulting table, which in this case has exactly the same schema as the input table, with the difference that the output table only contains those tuples that meet the condition we have given to the operator. This lets us perform more complex filtering on the stored data, such as retrieving rentals that have a price higher than a certain amount.</p>
<p>For example, by executing the following query, we’ll get all the tuples from Rental that have a price greater than 10. Specifically, we will get all their attributes, since we used * in the SELECT statement.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Rental <span class="hljs-keyword">AS</span> R 
<span class="hljs-keyword">WHERE</span> R.Price &gt; <span class="hljs-number">10</span>;
</code></pre>
<p>There are many possible conditions we can use in the WHERE clause. First, we can compare numeric attributes and strings with operators like &gt;, &lt;, &lt;=, or &lt;&gt;. These check when two things are different.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> Price &gt; <span class="hljs-number">50</span> <span class="hljs-keyword">AND</span> Duration &lt;&gt; <span class="hljs-number">7</span>;
<span class="hljs-comment">--The &lt;&gt; operator means values of the Duration attribute that differ from 7--</span>

<span class="hljs-keyword">SELECT</span> <span class="hljs-type">Name</span> 
<span class="hljs-keyword">FROM</span> Person 
<span class="hljs-keyword">WHERE</span> <span class="hljs-type">Name</span> &gt; <span class="hljs-string">'M'</span>;

<span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Person 
<span class="hljs-keyword">WHERE</span> <span class="hljs-type">Name</span> = <span class="hljs-string">'Carol King'</span>;
</code></pre>
<p>As you can see, the operators work the same with numbers as with text. But when using them with text, like in the comparison Name &gt; 'M', we get all the tuples with a Name value that is lexicographically after 'M'.</p>
<p>There are many options we can set for conditions regarding text values. For example, there are functions like LOWER() and UPPER() that convert text to lowercase and uppercase, respectively. We can also use LIKE to compare text with a pattern similar to a regular expression, where we have <strong>wildcard characters</strong> <strong>%</strong> and <strong>_</strong> (% denotes an arbitrary number of characters and <strong>_</strong> a single character).</p>
<p>We can also use the <strong>BETWEEN</strong> operator to check if a text is lexicographically between two others, but we can use it to compare other data types as well.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Person 
<span class="hljs-keyword">WHERE</span> Email <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'%@example.com'</span>;

<span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Person 
<span class="hljs-keyword">WHERE</span> LOWER(<span class="hljs-type">Name</span>) = <span class="hljs-string">'carol king'</span>;

<span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Person 
<span class="hljs-keyword">WHERE</span> <span class="hljs-type">Name</span> <span class="hljs-keyword">BETWEEN</span> <span class="hljs-string">'A'</span> <span class="hljs-keyword">AND</span> <span class="hljs-string">'M'</span>;

<span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> RentalDate <span class="hljs-keyword">BETWEEN</span> <span class="hljs-string">'2025-06-01'</span> <span class="hljs-keyword">AND</span> <span class="hljs-string">'2025-06-30'</span>;
</code></pre>
<p>Continuing with text operations, we also have the SIMILAR operator from the SQL-99 standard, which allows comparing text with regular expressions, using the same wildcard characters as in LIKE. But these regular expressions aren’t the ones we find in POSIX or Perl – they are simply expressions formed by the LIKE wildcard characters with a series of logical operators similar to those of conventional regular expressions.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Person 
<span class="hljs-keyword">WHERE</span> <span class="hljs-type">Name</span> <span class="hljs-keyword">SIMILAR</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">'(John|Jane)%'</span>; <span class="hljs-comment">--Match names starting with John or Jane--</span>

<span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Bike 
<span class="hljs-keyword">WHERE</span> Model <span class="hljs-keyword">SIMILAR</span> <span class="hljs-keyword">TO</span> <span class="hljs-string">'%[0-9]'</span>; <span class="hljs-comment">--Bike models ending in a number between 0 and 9--</span>
</code></pre>
<p>In addition to these operators, there are also the logical operators AND, OR, and NOT, which let us describe more complex conditions.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> (RentalDate <span class="hljs-keyword">BETWEEN</span> <span class="hljs-string">'2025-07-01'</span> <span class="hljs-keyword">AND</span> <span class="hljs-string">'2025-07-31'</span>) <span class="hljs-keyword">AND</span> (Price &gt; <span class="hljs-number">50</span>);

<span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Bike 
<span class="hljs-keyword">WHERE</span> Weight &lt; <span class="hljs-number">9.0</span> <span class="hljs-keyword">OR</span> Model <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'%Trek%'</span>;
<span class="hljs-comment">--Parentheses are not mandatory, but highly recommended--</span>

<span class="hljs-keyword">SELECT</span> <span class="hljs-number">1</span> <span class="hljs-keyword">AS</span> ColumnOfOnes
<span class="hljs-keyword">FROM</span> Bike 
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> (Weight &gt; <span class="hljs-number">10.0</span>);
</code></pre>
<p>Here we can see how in the SELECT clause of the last query, instead of returning an attribute, we return a literal, which is a numeric value of 1. If we look at the result, we’ll get a table with a single attribute, ColumnOfOnes, which is what we want to get by putting it in the SELECT list.</p>
<p>As for the tuples, it returns as many as there are in Bike that meet the WHERE condition, although we won't see their values. Instead, each tuple will only have the value 1 for the attribute ColumnOfOnes, which is what we've named these 1 values.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *, (Price / Duration) <span class="hljs-keyword">AS</span> Ratio 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> (Price / Duration) &gt; <span class="hljs-number">5</span>;

<span class="hljs-keyword">SELECT</span> *, (Price*<span class="hljs-number">1.0</span> / Duration) <span class="hljs-keyword">AS</span> Ratio 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> (Price*<span class="hljs-number">1.0</span> / Duration) &gt; <span class="hljs-number">5</span>;
</code></pre>
<p>When we’re using arithmetic operators, it's important to consider the data types being used. We have all the usual arithmetic operators +, -, *, and /. But when using division, if we don't perform any explicit casting, the division might be done as an integer division, providing a rounded result that may be far from what we need.</p>
<p>To get an exact division with all decimals, we can multiply either of the operands by 1.0 to force the DBMS to treat it as a decimal value. But we always have the option to multiply the operation by a certain amount like 100 so that the final result is an integer instead of a decimal, especially when calculating ratios.</p>
<p>Of course, in addition to arithmetic operations, SQL offers a series of functions that allow us to perform more advanced mathematical operations like the following:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span>
  ABS(<span class="hljs-number">-3.5</span>)      <span class="hljs-keyword">AS</span> abs,
  CEIL(<span class="hljs-number">2.1</span>)      <span class="hljs-keyword">AS</span> ceil,
  FLOOR(<span class="hljs-number">2.9</span>)     <span class="hljs-keyword">AS</span> floor,
  ROUND(<span class="hljs-number">2.345</span>,<span class="hljs-number">2</span>) <span class="hljs-keyword">AS</span> round,
  TRUNC(<span class="hljs-number">2.345</span>,<span class="hljs-number">1</span>) <span class="hljs-keyword">AS</span> trunc,
  SQRT(<span class="hljs-number">16</span>)       <span class="hljs-keyword">AS</span> sqrt,
  POWER(<span class="hljs-number">3</span>,<span class="hljs-number">4</span>)     <span class="hljs-keyword">AS</span> power,
  MOD(<span class="hljs-number">17</span>,<span class="hljs-number">5</span>)      <span class="hljs-keyword">AS</span> mod;

<span class="hljs-keyword">SELECT</span> 
  EXP(<span class="hljs-number">1</span>)       <span class="hljs-keyword">AS</span> e_to_1, <span class="hljs-comment">--The number e raised to the 1 power--</span>
  LN(<span class="hljs-number">10</span>)       <span class="hljs-keyword">AS</span> ln10,
  LOG(<span class="hljs-number">10</span>,<span class="hljs-number">100</span>)  <span class="hljs-keyword">AS</span> logBase10Of100; <span class="hljs-comment">--Logarithm base 10 of the number 100--</span>

<span class="hljs-keyword">SELECT</span>
  SIN(PI()/<span class="hljs-number">2</span>)   <span class="hljs-keyword">AS</span> sin90deg,
  COS(<span class="hljs-number">0</span>)        <span class="hljs-keyword">AS</span> cos0deg,
  TAN(PI()/<span class="hljs-number">4</span>)   <span class="hljs-keyword">AS</span> tan45deg;
</code></pre>
<p>On the other hand, SQL allows performing bit-level logical operations, such as a bitwise AND of the binary representation of two numbers, or a shift of their bits, among others.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span>
  <span class="hljs-number">9</span>  &amp; <span class="hljs-number">5</span>   <span class="hljs-keyword">AS</span> bitwiseAnd,
  <span class="hljs-number">9</span>  | <span class="hljs-number">5</span>   <span class="hljs-keyword">AS</span> bitwiseOr,
  <span class="hljs-number">9</span>  # <span class="hljs-number">5</span>   <span class="hljs-keyword">AS</span> bitwiseXor,
  <span class="hljs-number">1</span> &lt;&lt; <span class="hljs-number">3</span>   <span class="hljs-keyword">AS</span> shiftLeft,
  <span class="hljs-number">16</span> &gt;&gt; <span class="hljs-number">2</span>  <span class="hljs-keyword">AS</span> shiftRight;
</code></pre>
<p>Finally, if we want to check whether an attribute contains the value NULL or not, we can’t use the = operator. Instead, we have to use a specific operator called IS for this comparison:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Person 
<span class="hljs-keyword">WHERE</span> Email <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>; <span class="hljs-comment">--NULL can't be compared with = operator, but with IS --</span>
</code></pre>
<h4 id="heading-union-intersect-and-except">UNION, INTERSECT, and EXCEPT</h4>
<p>There are other relational algebra operators that are useful and have equivalent SQL statements, like those that operate on sets of tuples. So far, we have treated tables as if they were multisets because SQL allows duplicate tuples by default. But there are situations where it’s clearer to use operations on tables by treating them as if they were sets of tuples.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> BikeFK <span class="hljs-keyword">AS</span> BikeID 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> Duration &gt; <span class="hljs-number">3</span> 
<span class="hljs-keyword">UNION</span> 
<span class="hljs-keyword">SELECT</span> BikeFK 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> Price &lt;= <span class="hljs-number">15</span>;
</code></pre>
<p>For example, when we make a query, it returns a table with tuples, which we can see as a set of tuples. So, if we have several queries that return tables with the same number of columns and all of them have compatible data types (meaning they’re either the same or convertible by the DBMS), then we can perform a set operation between them, like a union of both sets of tuples. This in turn results in another set of tuples containing all those from both initial sets.</p>
<p>We do this using the UNION operator, which by default removes duplicate tuples since it treats the tables as sets of tuples. In this specific example, we’re performing a union between a set of tuples with the schema (BikeID) and another (BikeFK). Since both schemas have the same number of attributes with the same data types, regardless of their names, we can perform their union, resulting in a final table that contains all the tuples from both, removing duplicates.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> PersonFK, RentalDate <span class="hljs-keyword">AS</span> DateName 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> RentalDate &lt; <span class="hljs-string">'2025-01-01'</span> 
<span class="hljs-keyword">INTERSECT</span> 
<span class="hljs-keyword">SELECT</span> PersonFK, RentalDate <span class="hljs-keyword">AS</span> DateName2 <span class="hljs-comment">/*This name is not preserved, the above one does*/</span> 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> RentalDate &gt; <span class="hljs-string">'2024-01-01'</span>;
</code></pre>
<p>Besides performing a union, we can also carry out other common set operations like intersection or difference. For example, with INTERSECT, we only keep the tuples that are in both sets of tuples, removing duplicates, as long as we’ve made sure that both sets are valid for performing a set operation between them.</p>
<p>This means that to apply INTERSECT, we have to ensure that the schema of both sets is compatible, both in the number of columns, in this case, 2, and in their respective data types. As for the names, we see here that it doesn't matter what the attributes are called, since the result will always retain the schema name from the first set in the operation.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> PersonFK, RentalDate 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> RentalDate &lt; <span class="hljs-string">'2025-01-01'</span> 
<span class="hljs-keyword">EXCEPT</span> <span class="hljs-keyword">ALL</span>
<span class="hljs-keyword">SELECT</span> PersonFK, RentalDate 
<span class="hljs-keyword">FROM</span> Rental 
<span class="hljs-keyword">WHERE</span> RentalDate &gt; <span class="hljs-string">'2024-01-01'</span>;
</code></pre>
<p>Lastly, we can also calculate the difference between several sets with EXCEPT, which in some DBMS is called MINUS. This is the only operator where the order of the sets matters, meaning the one above discards the tuples that exist in the set below, so we are left with all the tuples that are in the first set but not in the second. Like the previous ones, this operator also removes duplicate tuples, so if we need to keep them, we have to add ALL after the set operator.</p>
<h4 id="heading-nested-query">Nested query</h4>
<p>We talked about nested queries back at the beginning as a way to use the result of one query within another query. Essentially, that's what it is, but SQL provides a series of specific operators that are useful when working with nested queries in a WHERE clause for example, since they can’t only be placed in the FROM clause.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> (
    <span class="hljs-keyword">SELECT</span> PersonFK,
      RentalDate
    <span class="hljs-keyword">FROM</span> Rental
    <span class="hljs-keyword">WHERE</span> RentalDate &gt; <span class="hljs-string">'2024-01-01'</span>
  ) <span class="hljs-keyword">AS</span> T
<span class="hljs-keyword">WHERE</span> T.RentalDate &lt;= <span class="hljs-string">'2024-06-06'</span>;
</code></pre>
<p>To start, nested queries take advantage of the fact that a query always returns a table, allowing us to use that result as an intermediate table in another query's computation.</p>
<p>For example, here we first get the tuples from Rental with a date later than 2024 in the subquery of the FROM clause. Then in the “outer” query, we assign the alias T to the result of this subquery, from which we get all its tuples with a date earlier than '2024-06-06'.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Rental R
<span class="hljs-keyword">WHERE</span> R.RentalDate &gt; <span class="hljs-string">'2024-01-01'</span><span class="hljs-keyword">AND</span> R.RentalDate &lt;= <span class="hljs-string">'2024-06-06'</span>;
</code></pre>
<p>As you might guess, when doing this, SQL internally first resolves the subquery in the FROM clause. This means it retrieves all the tuples that the subquery needs to return, and then applies the filter defined in the WHERE clause to all of them. So a condition is first evaluated on all the tuples from Rental, and then another condition is applied to all the resulting tuples from the query. This creates extra work (computation) to first obtain and potentially store in memory the tuples from the subquery and then filter them again.</p>
<p>Just note that conceptually, a derived table is evaluated first, but optimizers may rewrite/flatten the query – so don’t rely on a specific evaluation order.</p>
<p>On the other hand, this query could have been resolved more simply, as shown above. Here, the Rental table is used directly in the FROM clause, and filtering is applied with the two conditions on <strong>RentalDate</strong> "together" in a single WHERE clause. This means that only the tuples from Rental need to be traversed, instead of traversing them and then having to filter the tuples from a subquery again. This saves unnecessary computation as well as possible memory that the DBMS might use to store the resulting tuples from the subquery in memory.</p>
<p>With this example, we’ve seen that the same query can be resolved in a more or less computationally efficient way depending on how we plan to implement it. Although, generally, all modern DBMS have the <strong>Optimizer</strong> component in their architecture, which automatically applies certain <a target="_blank" href="https://www.geeksforgeeks.org/dbms/advanced-query-optimization-in-dbms/">optimization techniques</a> to the query without us having to worry about it. We won’t go into detail about these techniques here.</p>
<p>In turn, nesting these queries allows us to solve more complex problems with the help of operators like EXISTS. Specifically, we mainly use EXISTS in a WHERE statement before a nested query to check if the nested query contains any tuples or not. In other words, if we consider it as a multiset of tuples, EXISTS tells us whether that multiset is empty or not.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> B.*
<span class="hljs-keyword">FROM</span> Bike <span class="hljs-keyword">AS</span> B
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">EXISTS</span> (
    <span class="hljs-keyword">SELECT</span> *
    <span class="hljs-keyword">FROM</span> Rental <span class="hljs-keyword">AS</span> R
    <span class="hljs-keyword">WHERE</span> R.BikeFK = B.BikeID
  );
</code></pre>
<p>For example, to find out which bikes from Bike have been rented at least once, we select all those tuples from Bike that have a tuple in Rental associated with the bike we are checking.</p>
<p>To understand this, you need to keep in mind that a SQL query is usually executed by scanning the tuples of the tables from top to bottom. So the WHERE clause of the outer query is actually executed for each bike in Bike, which is the table we traverse in the FROM clause.</p>
<p>So for each bike, we execute a nested query that returns all rentals of that bike, as it keeps the tuples from Rental whose foreign key BikeFK points to the BikeID attribute of the table with alias B. This is called <strong>correlated nesting</strong> because we’re using the table from the outer query in the nested query. This means we may be forcing SQL to recalculate it each time the WHERE condition is checked on a tuple from Bike (but engines commonly rewrite it as a semi-join, avoiding per-row re-execution).</p>
<p>With this, if the nested query contains any tuple, it implies that the bike has been rented at least once. And we can detect this with EXISTS, which checks if the resulting table from the nested query returns any tuple.</p>
<p>Since we’re simply interested in knowing if it contains any tuple, we don’t need to return any specific attribute in the nested query, although it’s generally considered good practice to return *, or a constant like 1.</p>
<p>Another way to solve the previous query with a different operator is by using IN. This operator checks if a certain value or tuple is contained in a column or table.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> B.*
<span class="hljs-keyword">FROM</span> Bike <span class="hljs-keyword">AS</span> B
<span class="hljs-keyword">WHERE</span> B.BikeID <span class="hljs-keyword">IN</span> (
    <span class="hljs-keyword">SELECT</span> Rental.BikeFK
    <span class="hljs-keyword">FROM</span> Rental
  );
</code></pre>
<p>For example, in this case, we build a nested query in the WHERE clause that contains only the foreign key BikeFK from the Rental table, where all the BikeID values referenced by the rental tuples are found. In the outer query, all the tuples from Bike are traversed. It checks a condition where the BikeID from the Bike table must belong to the resulting table from the nested query to be considered a bike that’s been rented at least once.</p>
<p>So to solve this query, we need to know, for each bike, if its primary key BikeID is referenced by the corresponding foreign key of any tuple in Rental.</p>
<p>For this, we can use EXISTS as before to check if there is any tuple in Rental that references the specific primary key value of Bike, or we can use IN to directly check if the primary key value BikeID of the bike we are traversing in the outer query is present in the foreign key column of Rental that we get with the nested query.</p>
<p>Continuing with the equivalent ways to solve the previous query, we can also replace the IN operator with <strong>\=ANY</strong>. Intuitively, we can understand this as checking if the value B.BikeID is equal to any of the values in the column that we got with the nested query (which is equivalent to what the IN operator does).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> B.*
<span class="hljs-keyword">FROM</span> Bike <span class="hljs-keyword">AS</span> B
<span class="hljs-keyword">WHERE</span> B.BikeID = <span class="hljs-keyword">ANY</span> (
    <span class="hljs-keyword">SELECT</span> Rental.BikeFK
    <span class="hljs-keyword">FROM</span> Rental
  );
</code></pre>
<p>In other words, conceptually, checking if something belongs to a set is equivalent to checking if it’s equal to any of the elements contained in the set. Ultimately, the ANY operator allows us to check if a certain value meets a condition with respect to any of the values stored in a nested query – that is, in a multiset, since we can do it with tuples as well as values.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> B.*
<span class="hljs-keyword">FROM</span> Bike <span class="hljs-keyword">AS</span> B
<span class="hljs-keyword">WHERE</span> (<span class="hljs-number">1</span>, B.BikeID) = <span class="hljs-keyword">ANY</span> (
    <span class="hljs-keyword">SELECT</span> R.PersonFK, R.BikeFK
    <span class="hljs-keyword">FROM</span> Rental R
  );
</code></pre>
<p>For example, instead of checking if a specific value of a single attribute is in the column from the nested query, we can perform the check with a complete tuple.</p>
<p>Here, the nested query returns the foreign key values of the tuples from <strong>Rental</strong>, so in the outer query, we can check which bikes have been rented at least once by the person with the primary key <strong>PersonID=1</strong>. Or put another way, for each tuple in <strong>Bike</strong>, we check if there is any tuple in the nested query table in the form <strong>(1, B.BikeID)</strong>. This would indicate that the person with the primary key <strong>PersonID=1</strong> has rented the bike at least once.</p>
<p>Lastly, the IN operator is also equivalent to the <strong>NOT &lt;&gt; ALL</strong> operation, which is more complicated to understand. Essentially, we want to check if the tuple (1, B.BikeID) is contained in the result of the nested query.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> B.*
<span class="hljs-keyword">FROM</span> Bike <span class="hljs-keyword">AS</span> B
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> (<span class="hljs-number">1</span>, B.BikeID) &lt;&gt; <span class="hljs-keyword">ALL</span> (
    <span class="hljs-keyword">SELECT</span> R.PersonFK, R.BikeFK
    <span class="hljs-keyword">FROM</span> Rental R
  );
</code></pre>
<p>With <strong>&lt;&gt; ALL</strong>, we check if the tuple is different from each and every tuple stored in the nested query. Then, by negating that result with NOT, we can determine if that condition is not met (that is, the tuple is not different from each and every tuple in the nested query). This would mean it’s equal to at least one of them, or in other words, it’s contained in the multiset returned by the nested query.</p>
<p>To understand the ALL operator, we can try to get the bike with the lowest weight in the entire Bike table. To do this, with a nested query, we can get all the weights from the Bike table. Then in the outer query, we can go through all the tuples in Bike and check if each one’s weight B.Weight is less than or equal to each weight gotten with the nested query using <strong>&lt;= ALL</strong>.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span>   Bike B
<span class="hljs-keyword">WHERE</span>  B.Weight &lt;= <span class="hljs-keyword">ALL</span> (
    <span class="hljs-keyword">SELECT</span> Weight
    <span class="hljs-keyword">FROM</span>   Bike
);
</code></pre>
<p>If this is true, then that weight will match the lowest in the entire table, so the WHERE condition will be TRUE, and the corresponding tuple from Bike will be returned in our outer query.</p>
<p>In SQL, conditions usually return TRUE or FALSE values depending on whether they are met. But when comparing with NULL values, UNKNOWN is returned, since there are times when a nested query unexpectedly returns NULL values. This causes conditions that compare with those values to not result in logical truth values, but in the special value <strong>UNKNOWN</strong>.</p>
<h4 id="heading-join">JOIN</h4>
<p>The JOIN operators also have an equivalent in relational algebra. Their main purpose is to gather information spread across multiple tables so that all the data can be operated on in a single intermediate table.</p>
<p>For example, when we look at the information in the Rental table, we see that it has foreign keys referencing Bike and Person, but the Rental table itself doesn’t contain all the information we might need about the bikes or the people. So, if we want to query the rentals and the names of the people involved in those rentals, we’ll need to apply a JOIN operation on both tables.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Rental, Person;
</code></pre>
<p>There are several types of JOIN, all of which have an almost direct equivalence in relational algebra operators. The simplest one is the implicit JOIN shown above, which is denoted by using multiple tables in a FROM statement separated by commas. We can use as many tables as we want here, as long as there are no ambiguities in their names.</p>
<p>Note that if we perform an implicit JOIN of a table with itself, we’ll need to assign different aliases to the different uses we make of it.</p>
<p>Before seeing what the query does, it's useful to understand the Cartesian product operation in detail, as it’s the foundation of all SQL JOIN operators.</p>
<p>The <strong>Cartesian product</strong> is a mathematical operation that takes two sets as input, which in SQL are tables or multisets with tuples, such as table <strong>A</strong> with tuples <strong>{{a},{b},{c}}</strong>, and table <strong>B</strong> with tuples <strong>{{1},{2},{3}}</strong>. As output, the operation generates a new multiset of tuples where each row of A is <strong>combined</strong> with each row of B, resulting in the table or multiset <strong>A×B={{a,1},{a,2},{a,3},{b,1},{b,2},{b,3},{c,1},{c,2},{c,3}}</strong>.</p>
<p>As you can see, if table <strong>A</strong> has <strong>n</strong> tuples and table <strong>B</strong> has <strong>m</strong> tuples, the Cartesian product will generate <strong>n*m</strong> tuples, where each one takes values from all the attributes of table <strong>A</strong> and table <strong>B</strong> (since the result of the operation includes all possible <strong>“pairings“</strong> we can make between tuples from both tables).</p>
<p>So going back to our query, as you can see in the result, the implicit JOIN performs the Cartesian product of the two tables. It doesn't matter if their names repeat, as each repetition can be accessed through a different alias.</p>
<p>Regarding the tuples it contains, we see that the Cartesian product returns tuples where each possible tuple of Rental is combined with each possible tuple of Person. This forms tuples with values in all the attributes of the resulting <strong>JOIN</strong> table.</p>
<p>The implicit join has no filtering criteria or additional functionality – it simply returns the complete Cartesian product of the tables involved in the operation.</p>
<p>Its name, implicit, comes from the fact that the JOIN operator and the type of JOIN we want to perform aren’t explicitly written. Instead, it's enough to list several tables separated by a comma in the FROM clause.</p>
<p>In addition to the implicit JOIN, we also have the explicit JOIN. It can be of various types depending on the filtering or conditions applied to the Cartesian product.</p>
<p>For example, instead of performing a Cartesian product between both tables with an implicit join, we can also do it explicitly with a <strong>CROSS JOIN</strong>. This does exactly the same thing but with explicit syntax: we specify the JOIN operation to perform and its type, CROSS. This indicates the execution of a Cartesian product like the previous one.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Rental <span class="hljs-keyword">CROSS</span> <span class="hljs-keyword">JOIN</span> Person;
</code></pre>
<p>Besides the CROSS type, there are other types that provide additional functionalities to the JOIN, allowing us to filter the tuples we get from a Cartesian product.</p>
<p>For example, so far with the Cartesian product, we have obtained all combinations of tuples from Rental and Person. If there are N tuples in Rental and M tuples in Person, then the Cartesian product will return N*M tuples – meaning all possible combinations of tuples from both tables we are working with.</p>
<p>If we look at the resulting table from this operation, we will see that some values of different attributes like PersonPK and PersonID match in the same tuple. This means a tuple from Rental has been combined with a tuple from Person so that this is the person referenced by the foreign key in Rental. In other words, we have a tuple that not only contains the information from Rental but also has the information from the Person tuple representing the person who made that rental – and it’s been"concatenated" or combined with it.</p>
<p>So if we want to keep only those tuples from the Cartesian product where PersonFK matches PersonID from the Person table, we could apply a condition in a WHERE clause to filter those tuples. But by doing this, conceptually this is a Cartesian product followed by a filter, but the optimizer typically rewrites it into an equivalent inner join without materializing the full product.</p>
<p>There are specific types of JOINs that can help us perform this filtering more efficiently:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Rental <span class="hljs-keyword">AS</span> R <span class="hljs-keyword">CROSS</span> <span class="hljs-keyword">JOIN</span> Person <span class="hljs-keyword">AS</span> P
<span class="hljs-keyword">WHERE</span> R.PersonFK=P.PersonID;

<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Rental R <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person <span class="hljs-keyword">AS</span> P <span class="hljs-keyword">ON</span> R.PersonFK=P.PersonID;
</code></pre>
<p>To implement this query, we can use a condition in a WHERE clause, or we can use an INNER JOIN, which allows us to set a condition in the ON clause.</p>
<p>If we use a WHERE clause, we’ll be filtering all the tuples obtained from the complete Cartesian product resulting from the CROSS JOIN using a condition. But to avoid creating the entire Cartesian product (which isn’t efficient), we can use an explicit INNER JOIN. Here, we can provide a condition in the ON clause so that only the tuples from the Cartesian product that meet that condition are actually constructed.</p>
<p>In the ON clause of an INNER JOIN, we can put any type of condition on the tuples we want to get. But there are times when these conditions are simple and only involve equality between attributes, which may even have the same name.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P1 <span class="hljs-keyword">CROSS</span> <span class="hljs-keyword">JOIN</span> Person P2
<span class="hljs-keyword">WHERE</span> P1.PersonID=P2.PersonID;

<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P1 <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P2 <span class="hljs-keyword">ON</span> P1.PersonID=P2.PersonID;
</code></pre>
<p>For example, if we perform the Cartesian product between the Person table and itself, and we want to keep only those tuples where the PersonID attributes of both tables match, we can use an INNER JOIN with the condition that the PersonIDs of both tables being combined are equal. This way, only the tuples that meet this condition will be constructed (unlike the previous query where using a CROSS JOIN implies constructing all tuples of the Cartesian product, which requires more computation).</p>
<p>In these types of situations, instead of using an INNER JOIN, we can take advantage of another type of JOIN like the NATURAL JOIN. This returns only those tuples where the values of all attributes with the same name match.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P1 <span class="hljs-keyword">NATURAL</span> <span class="hljs-keyword">JOIN</span> Person P2;

<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P1
  <span class="hljs-keyword">NATURAL</span> <span class="hljs-keyword">JOIN</span> (
    <span class="hljs-keyword">SELECT</span> PersonID,
      <span class="hljs-type">Name</span> <span class="hljs-keyword">AS</span> Name2,
      Birth <span class="hljs-keyword">AS</span> Birth2,
      Email <span class="hljs-keyword">AS</span> Email2
    <span class="hljs-keyword">FROM</span> Person
) <span class="hljs-keyword">AS</span> P2;
</code></pre>
<p>To understand this, we can perform a NATURAL JOIN between the Person table and itself. First, if we don't rename any attribute, then all will have the same name in both tables – so the NATURAL JOIN will impose an equality condition for each attribute. This means that it’ll return only those tuples that satisfy <strong>P1.PersonID=P2.PersonID</strong>, <strong>P1.Name=P2.Name</strong>, and so on for the rest of the attributes, since they have the same name despite being in tables with different aliases. This will result in the same Person table, as the NATURAL JOIN, in addition to imposing these conditions, "merges" attributes that meet these conditions. So if they have the same name, it leaves only one occurrence of them, not both (as happens in other types of JOINs).</p>
<p>But if we rename the attributes of one of the tables except for PersonID, we’ll see that NATURAL JOIN only imposes the equality condition <strong>P1.PersonID=Person.PersonID</strong>, since PersonID is the only attribute that’s exactly the same in both tables.</p>
<p>In the resulting table, we’ll get the same as before but with the renamed attributes included, as they aren’t discarded or subjected to any condition that makes them unnecessary. Even if we rename PersonID as well, we’ll get the Cartesian product of Person with itself – because if none of the attributes have the same name in both tables, then NATURAL JOIN doesn’t impose any equality condition.</p>
<p>Another option we have to impose equality conditions on attributes with the same name in both tables is to use an INNER JOIN. Instead of declaring conditions in an ON clause, we use a USING clause where we define the attributes on which equality conditions are imposed. These must have exactly the same name in both tables.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P1 <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P2 <span class="hljs-keyword">USING</span> (PersonID);
</code></pre>
<p>For example, in the query above, we are getting the tuples from the Cartesian product of Person with itself that satisfy <strong>P1.PersonID=P2.PersonID</strong>.</p>
<p>The main difference with NATURAL JOIN is that NATURAL JOIN tries to impose this equality condition on all possible attributes with the same name. But with an INNER JOIN and USING, we decide which equality conditions are imposed on which attributes (as long as they have the same name in both tables). Otherwise, the DBMS might generate an error.</p>
<p>Also, when we use USING in combination with an INNER JOIN, only one occurrence of the attributes with the same name appears in the resulting table, just like with NATURAL JOIN.</p>
<p>Lastly, it’s important to note that when using ON to declare a condition, no attribute is removed from the resulting table of the <strong>JOIN operation</strong>, since the condition can be <strong>very diverse</strong> in nature. This means it doesn't necessarily have to be an equality between several attributes.</p>
<p>But when you’re using USING in combination with an INNER JOIN (and imposing an equality condition on the attributes declared in the USING clause), all repetitions of those attributes will be removed from the resulting table. So, if we impose an equality condition on several attributes with the same name, all but one of their occurrences will be deleted.</p>
<p>For example, in a table with two attributes called PersonID but coming from different tables or elements with different aliases (same Person table but different alias), USING would remove one of their occurrences. This would leave only one PersonID attribute in the resulting JOIN table, while ON would not remove any of the occurrences. And. this would result in the final table containing both original PersonID attributes.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P <span class="hljs-keyword">LEFT JOIN</span> Rental R <span class="hljs-keyword">ON</span> R.PersonFK = P.PersonID;
</code></pre>
<p>Continuing with the types of JOIN, there might be a case where a person has never rented a bike, so there won't be any tuple in the Rental table referencing that person. This is possible due to the minimum multiplicities on the Rental side in the entity-relationship diagram (that don’t require any person to have rented a bike).</p>
<p>So if we want to build a table that shows information about all people along with information about all the rentals they’ve made, the first thing we may think of is performing an INNER JOIN between them. And we’d add a certain equality condition on the foreign key attribute of Rental that references the primary key of the Person table.</p>
<p>But there may be people who have never rented. abike, so if we do an INNER JOIN, the information about these people won’t appear in the table. To make sure that they appear, we need to use an OUTER JOIN instead of an INNER JOIN. We also need to specify which table we want to force to have its data appear by putting LEFT or RIGHT before the type of <strong>OUTER JOIN</strong> (or we can simply use <strong>LEFT JOIN</strong>, for example).</p>
<p>This way, if we use LEFT JOIN, we’re forcing the data from the table on the left of the JOIN to appear in the resulting table. If they have no match in the table on the right (meaning if they have no rental), then the other attributes will be filled with NULL values, as we saw in the result of the previous query.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Rental R <span class="hljs-keyword">RIGHT OUTER JOIN</span> Person P <span class="hljs-keyword">ON</span> R.PersonFK = P.PersonID;
</code></pre>
<p>In the same way, if we use RIGHT JOIN and reverse the order of the tables, we’ll do the same but force the data from the table on the right to appear in the resulting table, filling the attributes of the left table with NULL in case there’s no match.</p>
<p>With Rental RIGHT JOIN Person, all persons appear – for persons without rentals, the Rental side will be NULL.</p>
<p>Finally, if we want to use both RIGHT and LEFT in a join and force the data from both tables to appear (which would fill in NULL on the side that corresponds to each tuple), we can use a FULL JOIN.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P <span class="hljs-keyword">JOIN</span> Rental R <span class="hljs-keyword">ON</span> R.PersonFK = P.PersonID;
</code></pre>
<p>In this last type of JOIN, we've seen that specifying OUTER is optional when using RIGHT, LEFT, or FULL. But by default, if nothing is specified, the JOIN operator is treated as an INNER type, requiring a condition with ON or USING afterward.</p>
<h4 id="heading-aggregation">Aggregation</h4>
<p>With joins, we can now combine several tables and gather their information into one. But there are still certain operations we can't do easily, like counting the rows in a table, summing the values of a column, calculating their average, and so on.</p>
<p>All operations of this nature that involve values from a multiset (table) of tuples are called aggregation operations. Their goal is to perform a calculation on a series of tuples and are the basis of analytical queries.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> COUNT(*) <span class="hljs-keyword">AS</span> rentalCount,
  SUM(Price) <span class="hljs-keyword">AS</span> income,
  AVG(Price) <span class="hljs-keyword">AS</span> averageRentalPrice,
  MAX(Price) <span class="hljs-keyword">AS</span> maxRentalPrice,
  MIN(Price) <span class="hljs-keyword">AS</span> minRentalPrice
<span class="hljs-keyword">FROM</span> Rental;
</code></pre>
<p>SQL offers a number of them (which don’t have a direct equivalent with relational algebra operators): COUNT(), SUM(), AVG(), MIN(), and MAX().</p>
<h4 id="heading-count">COUNT()</h4>
<p>We can use COUNT() to count how many rows are in a table, including tuples where all values are NULL. So by declaring COUNT(*) in the SELECT clause, we’ll get the number of tuples in the table specified in the FROM clause.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> COUNT(*), COUNT(Price), COUNT(<span class="hljs-keyword">DISTINCT</span> Price)
<span class="hljs-keyword">FROM</span> Rental;
</code></pre>
<p>But the function can also perform aggregation on a specific column. So instead of counting tuples, it counts how many values exist in a certain attribute, including duplicate values and ignoring NULLs.</p>
<p>So if we want to count only how many distinct values there are in Price, we can use DISTINCT as shown above.</p>
<p>As for the column names we get from these operations, it's not mandatory to assign them an alias and rename them, but it's very convenient for identifying which calculation is stored in each column of the resulting table.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> COUNT(*) 
<span class="hljs-keyword">FROM</span> (<span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">DISTINCT</span> PersonFK, BikeFK <span class="hljs-keyword">FROM</span> Rental) <span class="hljs-keyword">AS</span> t;
</code></pre>
<p>In addition to a single attribute, COUNT() can count how many combinations of values from a certain set of attributes are in the table. Specifically, in this example, we are counting how many <strong>(PersonFK, BikeFK)</strong> values are in the table. This may not match the total number of tuples since NULLs are ignored here, unlike in the <strong>COUNT(*)</strong> operation where they are also considered. We can also use DISTINCT here, as long as the attributes whose value combinations we want to count are in parentheses.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> SUM(<span class="hljs-number">2</span>*Price), AVG(Price)
<span class="hljs-keyword">FROM</span> Rental;
</code></pre>
<h4 id="heading-sum">SUM()</h4>
<p><strong>SUM()</strong> calculates the sum of a certain numeric attribute of a table, or an attribute that can be converted to numeric. It takes as input the attribute from which we want to get the sum of all values present in the table. Note that, besides the attribute, SUM() accepts expressions that result in a single attribute. That is, if instead of <strong>Price</strong> we provide <strong>2*Price, or Price+Price</strong>, then those operations will be summing a series of attributes whose result will be stored in a single attribute. This is given as input to SUM().</p>
<p>If all the values of the attribute are NULL, SUM() returns 0. Unlike COUNT(), in this case, we can’t sum several attributes at once, meaning SUM() only takes one attribute as input, regardless of whether we get it through an arithmetic expression.</p>
<h4 id="heading-avg">AVG()</h4>
<p>Similarly, AVG() calculates the average of the values taken by a single attribute, ignoring NULLs. Unlike SUM(), this function returns NULL when all the values of the input attribute are NULL, since internally it can be calculated as <strong>SUM()/COUNT()</strong>.</p>
<p>So if SUM() returns 0 when counting an attribute full of NULLs and COUNT() ignores those NULL values, the average will be 0/0, which is undefined – causing AVG() to return NULL. It’s also important to note that if we use DISTINCT, both the sum and the average will be different.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> MIN(Price), MAX(Price)
<span class="hljs-keyword">FROM</span> Rental;
</code></pre>
<h4 id="heading-min-and-max">MIN() and MAX()</h4>
<p>Finally, the MIN() and MAX() operations take an attribute as input and return the minimum or maximum value found in the tuples stored in the table, respectively. If all the values of that attribute are NULL, they also return NULL, as a coherent minimum or maximum value can’t be established since NULLs are ignored.</p>
<h4 id="heading-group-by">GROUP BY</h4>
<p>If we try to use aggregate functions in the SELECT clause along with other attributes, the DBMS will give us an error because these types of functions are usually used together with the GROUP BY statement (this also doesn't have a direct equivalent in relational algebra).</p>
<p>To understand how GROUP BY works, we can calculate the sum of all the rental prices that a certain person has made in the system.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> SUM(Price)
<span class="hljs-keyword">FROM</span> Rental R
<span class="hljs-keyword">WHERE</span> R.PersonFK=<span class="hljs-number">5</span>;
</code></pre>
<p>To do this, we access the Rental table and use a WHERE clause to filter all rental tuples for a certain person using their foreign key that references the person making the rental. Then, with SUM, we get the sum of the Price attribute from the final table, which contains the prices of all rentals made by that person.</p>
<p>If we wanted to do it by name instead of PersonID, we would need to do a JOIN with the Person table and filter by the Name attribute of Person (although this isn’t important for understanding GROUP BY).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> SUM(Price) <span class="hljs-keyword">AS</span> PriceSum
<span class="hljs-keyword">FROM</span> Rental R <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P <span class="hljs-keyword">ON</span> R.PersonFK=P.PersonID
<span class="hljs-keyword">WHERE</span> P.Name=<span class="hljs-string">'Carol King'</span>;
</code></pre>
<p>Now, if we want to calculate this value for the rest of the people in the database who have ever rented a bike at least once, we would have to run this query multiple times for each person in the system, which isn’t practical. Instead, we can take advantage of the fact that the Rental table itself has the foreign key PersonFK for people who have rented bikes – and we can use this to calculate this sum for all of them more simply using GROUP BY.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> R.PersonFK, SUM(Price) <span class="hljs-keyword">AS</span> PriceSum 
<span class="hljs-keyword">FROM</span> Rental R 
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> R.PersonFK;
</code></pre>
<p>As you can see, this query returns all the people who have ever rented a bike – meaning those referenced from the Rental table. For each one, it calculates the sum of the prices of their rentals. This is possible thanks to GROUP BY, which groups all the tuples in the Rental table by the PersonFK attribute.</p>
<p>Since each person can have multiple rentals in the Rental table, we need to get all the tuples that reference each person and group them so that we can perform an aggregation operation like SUM() on one of the attributes.</p>
<p>In this case, we do the grouping with the PersonFK attribute, which identifies the person who made the rental. So since all the tuples in Rental with the same value in that attribute belong to the same person, they are grouped by that attribute to form groups of tuples, one for each person.</p>
<p>With this, we can then return the attribute that was grouped (which must be included in the SELECT when using GROUP BY) along with the results of the aggregation operations calculated on those groups.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">DISTINCT</span> Price
<span class="hljs-keyword">FROM</span> Rental;

<span class="hljs-keyword">SELECT</span> Price
<span class="hljs-keyword">FROM</span> Rental
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> Price;
</code></pre>
<p>When we use GROUP BY and partition the tuples of the table into groups, each group is "identified" or represented by one value of the attribute we are grouping by. This means that when we return a result to the user, for <strong>each group</strong>, they receive a single <strong>tuple</strong> where the attribute used for grouping takes the value of the "representative" of that group, instead of receiving multiple tuples per group.</p>
<p>For example, to get all the distinct prices from the Rental table, we can use DISTINCT directly, or we can also group by that attribute, which results in forming different groups of tuples, one for each distinct price. Finally, when returning Price after grouping, the distinct values of Price that form the different groups of tuples are returned, meaning only the distinct Price values are obtained.</p>
<p>It’s also worth noting that we can group by several attributes at once, not just one. In this case, we would generate groups of tuples based on the unique combinations of values those attributes take in the table.</p>
<p>Finally, when we use the GROUP BY statement in a query, we might want to filter and keep only the tuples whose aggregation operation results meet a certain condition. For example, to get only the people whose total rental price sum is greater than 100, we might think of using a WHERE clause with the following condition:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> R.PersonFK, SUM(Price) <span class="hljs-keyword">AS</span> PriceSum
<span class="hljs-keyword">FROM</span> Rental R
<span class="hljs-keyword">WHERE</span> PriceSum &gt; <span class="hljs-number">100</span>
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> R.PersonFK;

<span class="hljs-keyword">SELECT</span> R.PersonFK, SUM(Price) <span class="hljs-keyword">AS</span> PriceSum
<span class="hljs-keyword">FROM</span> Rental R
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> R.PersonFK
<span class="hljs-keyword">HAVING</span> SUM(Price) &gt; <span class="hljs-number">100</span>;
</code></pre>
<p>But if we use that condition in the WHERE clause, the DBMS will give us an error because we can’t impose conditions on the aggregation calculations in the groups in a WHERE clause. We also can’t refer to them with the alias we give them, since the alias is applied at the end of the query when the result is provided to the user.</p>
<p>So instead of using WHERE, when we want to implement this type of condition, we use HAVING. Instead of the alias, we use the expression SUM(Price) itself to refer to the sum of Price in each group. Using WHERE isn’t prohibited, because before doing the grouping, we can filter the data that appears in the FROM table, thus grouping fewer tuples.</p>
<h4 id="heading-order-by">ORDER BY</h4>
<p>Finally, if we want to sort the tuples of a table, we can use the ORDER BY clause. It lets us we specify one or more attributes on which the sorting is performed as well as a direction (which can be ASC or DESC for ascending or descending order, respectively).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> <span class="hljs-type">Name</span> <span class="hljs-keyword">ASC</span>;

<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> (PersonID, <span class="hljs-type">Name</span>) <span class="hljs-keyword">ASC</span>;
</code></pre>
<p>In sorting, certain attributes have higher priority. Those we place more to the left are sorted first, as in this last query that sorts the tuples of Person by their PersonID values and then by name.</p>
<p>So using all these clauses, we can start making SQL queries to get almost any type of result we need. As we have seen, queries are composed of a series of statements or clauses where each one performs a certain action on the tuples of a table.</p>
<p>These statements usually follow an <strong>order of appearance in the query</strong> that is important to follow to avoid DBMS errors. The order is as follows:</p>
<ol>
<li><p><code>SELECT</code></p>
</li>
<li><p><code>FROM</code></p>
</li>
<li><p><code>WHERE</code></p>
</li>
<li><p><code>GROUP BY</code></p>
</li>
<li><p><code>HAVING</code></p>
</li>
<li><p><code>ORDER BY</code></p>
</li>
</ol>
<p>But at a low level, the execution of these statements or equivalent relational algebra operators follows a different order than the one we use when writing the query. It is as follows:</p>
<ol>
<li><p><code>FROM</code></p>
</li>
<li><p><code>JOIN … ON</code></p>
</li>
<li><p><code>WHERE</code></p>
</li>
<li><p><code>GROUP BY</code></p>
</li>
<li><p><code>HAVING</code></p>
</li>
<li><p><code>SELECT</code></p>
</li>
<li><p><code>ORDER BY</code></p>
</li>
</ol>
<p>First, data is fetched from a table with the FROM clause, which may need to perform certain JOIN operations between multiple tables to have the data ready. Then, the data is filtered using the conditions we set in the WHERE clause, if we use it. After that, the tuples are grouped and filtered again if we use GROUP BY. Finally, the SELECT clause is applied to extract the attributes we are interested in from the final table, which we rename and order if necessary.</p>
<p>So as you can see, when we write a SQL query, we must use the clauses in a specific order. But we should keep in mind that the DBMS, at the physical and storage level, doesn’t execute these statements in the same order we write them. In fact, we don't have to worry too much about this internal order because it’s <a target="_blank" href="https://stackoverflow.com/questions/17384020/what-do-transparent-and-opaque-mean-when-applied-to-programming-concepts">transparent</a> (that is, handled automatically and hidden) to the user. This means we don't have direct control or "see" how the execution of the clauses is carried out internally by the DBMS, inspect the plan with <code>EXPLAIN/EXPLAIN ANALYZE</code>.</p>
<p>Regarding the internal execution order, the DBMS usually reorders, combines, or transforms the clauses into others, all while constructing a physical execution plan for the query. This involves generating a plan for the operations and internal resources needed to execute it optimally (hence the reordering).</p>
<p>This is important to know when constructing a query, as the way you program it can affect the efficiency of the query, even though the DBMS can help by automating much of the optimization process. You don’t have to use all these statements in a query, of course. But those you do use should respect the order in which they should be written, otherwise, the DBMS will likely end up throwing an error.</p>
<h3 id="heading-views">Views</h3>
<p>To finish with DML, let's look at a possible application of queries when defining DDL elements in SQL. Originally, we saw that DDL statements allowed us to create databases, tables, and similar elements. One of them worth highlighting is <strong>views</strong>, which are virtual tables that let us abstract information from the tables in a database.</p>
<p>Our database is made up of a schema or set of tables where the information is stored, but we might need to "view" that information differently than how it's defined in the schema itself. For this, we define a view that lets us query that information from the database using a different structure than the one used to store it.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">VIEW</span> RentalOverview <span class="hljs-keyword">AS</span>
<span class="hljs-keyword">SELECT</span> P.PersonID <span class="hljs-keyword">AS</span> PersonID,
  P.Name <span class="hljs-keyword">AS</span> ClientName,
  <span class="hljs-built_in">CURRENT_DATE</span> - P.Birth <span class="hljs-keyword">AS</span> ClientAge,
  B.BikeID <span class="hljs-keyword">AS</span> BikeID,
  B.Model <span class="hljs-keyword">AS</span> BikeModel,
  R.RentalDate <span class="hljs-keyword">AS</span> RentalDate,
  R.Duration <span class="hljs-keyword">AS</span> RentalDurationDays,
  R.Price <span class="hljs-keyword">AS</span> RentalTotalPrice
<span class="hljs-keyword">FROM</span> Rental R
  <span class="hljs-keyword">JOIN</span> Person P <span class="hljs-keyword">ON</span> R.PersonFK = P.PersonID
  <span class="hljs-keyword">JOIN</span> Bike B <span class="hljs-keyword">ON</span> R.BikeFK = B.BikeID;
<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> RentalOverview;
</code></pre>
<p>For example, in our database, we have the tables Rental, Bike, and Person, but for convenience or requirements, we might need to see all that information from the tables integrated into a single table with attributes <strong>(PersonID, ClientName, ClientAge, BikeID, BikeModel, RentalDate, RentalDurationDays, RentalTotalPrice)</strong>.</p>
<p>By default, every time we want to see this integrated information, we would have to manually run a query (or several, depending on the circumstances) to get and integrate that information into a table.</p>
<p>But to simplify this process, there are views that allow us to define a <strong>"virtual" table</strong> containing the integrated information. So, whenever we need that integrated information, we can refer to the virtual table (and this is built using the query we would have had to run manually to construct it). This query is the <strong>definition</strong> with which we declare a <strong>view</strong>, and the view itself saves us from having to run it manually to get the integrated information.</p>
<p>That's why we create a new view in the database that acts as a <strong>virtual table</strong> (meaning it doesn't actually store any information). This is because a view is a table that receives user queries, but to resolve them, it has to fetch information from different tables in the database.</p>
<p>So, as you can see in the view above, the virtual table RentalOverview is defined with a SQL query on the tables that do store information. So when we query RentalOverview, the DBMS is actually transforming our query using the view's definition to obtain the attribute ClientName, for example, which is defined as the name of the person who rented a bike.</p>
<p>In this specific case, our view is gathering all the information from the three tables into one, so when we query it, we have the complete information about the person, bike, and rental that occurred. We don't have to perform the JOINs ourselves, as they are part of the view's definition.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> RentalOverview;
</code></pre>
<p>When querying the virtual table, we’ll get information derived from the base tables, which is shown to us according to the schema we defined in the view. For example, in the database, the birth date of people is stored in the Birth attribute. But the view shows that data differently, displaying age instead of the birth date. Both refer to the same information but are viewed in different ways.</p>
<h3 id="heading-database-administration">Database Administration</h3>
<p>At the logical level where we implement the database with SQL, we need to perform ongoing database maintenance (in addition to data modeling, modification, and querying). This ensures that our data and services are available, optimizes query performance, and provides certain guarantees of security and integrity. This process is part of what is considered <strong>database administration</strong>, which is a task carried out by experts.</p>
<h4 id="heading-database-users">Database users</h4>
<p>Before introducing the concept of administration, let’s talk about the different types of users that might use a database. Each of them has a certain objective, responsibilities, and competencies.</p>
<p>To start, we have the <strong>client user</strong>, who uses the services provided by the database. We can see this type of user as an average user of mobile or web applications, or on any platform, using a series of services that involve a database.</p>
<p>Then, we have the <strong>developer user</strong>, who is dedicated to technically implementing the infrastructure, both software and hardware, that supports the applications and services. Developer users are also responsible for defining the business logic of the database, its structure, requirements, and so on. In short, they follow the different design stages we saw at the beginning, especially the conceptual and logical design, although they don’t interact with the DBMS. They simply propose the schema that the data should follow for a specialist to implement on a DBMS.</p>
<p>This specialist is the <strong>database administrator user</strong>, who is responsible for implementing the logical design of the database on a DBMS. To do this, they perform tasks such as choosing the appropriate DBMS for the project in question, installing it, and keeping it updated. They create the database, tables, and other logical elements, manage the security of the DBMS by defining roles, permissions, and security policies, and monitor the database's performance to ensure its availability. They also provide technical support to other types of users and define data backup protocols.</p>
<p>So basically, the administrator is in charge of the implementation during the logical design stage, as well as subsequent stages of possible physical design and storage. They’re also responsible for maintaining the DBMS. Among all these tasks, one of the most critical is optimizing the queries users might make to the system and refining the schemas if necessary to improve performance.</p>
<h4 id="heading-database-metadata">Database metadata</h4>
<p>So far, we have only considered that the database is responsible for storing information (data). These are ultimately generated by the project or application that the database supports, such as the tuples of the tables.</p>
<p>But in addition to these data, the database contains a series of metadata used to manage the data. Essentially, metadata primarily serves to describe another piece of data or provide additional information that helps organize it within the database. Here’s an example:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Name</strong></td><td><strong>Birth</strong></td><td><strong>Email</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Alice Johnson</td><td>1985-07-12</td><td>alice.johnson@example.com</td></tr>
<tr>
<td>Bob Smith</td><td>1990-03-05</td><td>bob.smith@example.org</td></tr>
<tr>
<td>Carol Davis</td><td>1978-11-23</td><td>carol.davis@example.net</td></tr>
<tr>
<td>David Brown</td><td>2001-01-30</td><td>david.brown@example.com</td></tr>
<tr>
<td>Emily Wilson</td><td>1995-09-14</td><td>emily.wilson@example.co.uk</td></tr>
</tbody>
</table>
</div><p>To understand the idea of metadata, we can introduce the concept of a schema as metadata. In a table, we have a table name, which is metadata that describes the table. This allows us to know which table we are referring to when using that name in a query or other situations.</p>
<p>Besides the name, all tables have a header composed of the names of the attributes located in the first row, which make up the table's schema. These names are used to refer to the attributes or columns, just as the table name is used to refer to the table itself as an object. So the schema is part of the metadata, as it provides meaning to the data stored in the columns, allowing them to be organized.</p>
<p>In other words, if we didn't have the first row with the attribute names, we would have no information about the stored data, as we would lack their semantics. This is precisely what the schema provides as metadata, which lets us manage them.</p>
<p>Apart from table and attribute names, tables usually have associated technical metadata from the DBMS. This metadata indicates the users who own the table or have certain permissions to perform actions on it. It also contains the creation and last modification dates of the table to ensure data security, existing connections, or information about events or locks for managing concurrency.</p>
<p>The table as an object does not store its name and all metadata within itself, but rather in specific places within the DBMS. These specific places are reserved tables for the DBMS called dictionaries, or sometimes catalogs. They utilize the structured nature of the DBMS to store this metadata in a simple way, similar to the storage of the actual data.</p>
<p>Since these places are tables, they also have a name, schema, and metadata, stored in the DBMS in physical data structures, not in other tables. As for their schemas, they are specially referred to as metaschemas.</p>
<p>The metadata in a DBMS varies significantly depending on the specific DBMS we’re using. But in all of them, we’ll always find fundamental information about the database we have implemented, like its name, table names, schemas, constraints, and so on.</p>
<p>Specifically, in PostgreSQL, we can find them in the "schemas" <strong>pg_catalog</strong> and <strong>information_schema</strong>. Here, PostgreSQL refers to a "schema" as a logical container that holds certain tables, views, and similar elements of a database, where many of them are responsible for storing metadata. So a logical container is nothing more than a folder used to group elements to make them more hierarchical and organized.</p>
<p>On one hand, <strong>pg_catalog</strong> is the internal catalog of PostgreSQL, which means it contains all the information necessary to manage the DBMS's operation. But this catalog is very technical and dense, as it’s aimed at managing the entire operation of the system, involving a lot of details that aren’t always necessary for an administrator.</p>
<p>Becuase of this, there’s a standard abstraction of this logical container called <strong>information_schema</strong>, introduced with the SQL-92 standard, which primarily serves to abstract the specific details related to the DBMS's operation and provide the database administrator with a series of views to better visualize and manage the metadata.</p>
<p>To know what pg_catalog contains, you can use commands like <strong>\dt pg_catalog.*</strong> to see the tables, views, or generally the elements it contains. Among all of them, the most important are:</p>
<ul>
<li><p><strong>pg_catalog.pg_class:</strong> Stores metadata of database objects, such as tables or views, among others.</p>
</li>
<li><p><strong>pg_catalog.pg_namespace:</strong> Stores the names of the schemas (logical containers) of the DBMS</p>
</li>
<li><p><strong>pg_catalog.pg_attribute:</strong> Stores the names of the attributes of tables or views, meaning their schemas, as well as their data types or user-defined domains.</p>
</li>
<li><p><strong>pg_catalog.pg_type:</strong> Stores the default data types and user-defined types.</p>
</li>
<li><p><strong>pg_catalog.pg_attrdef:</strong> Stores the default values defined for the attributes.</p>
</li>
<li><p><strong>pg_catalog.pg_constraint:</strong> Stores the definitions of constraints on tables, such as PRIMARY KEY, UNIQUE, FOREIGN KEY, CHECK, and EXCLUSION, including information about the table they apply to (conrelid), the columns involved (conkey), the update and delete actions on foreign keys (confupdtype, confdeltype), and the name of the constraint (conname), among others.</p>
</li>
<li><p><strong>pg_catalog.pg_stat_activity:</strong> Provides real-time information about active sessions on the PostgreSQL server.</p>
</li>
</ul>
<p>As you can see, if we explore the content of pg_catalog, we’ll find that it’s very dense and detailed. That's why we have the standard alternative <strong>information_schema</strong>, which simplifies metadata management. It works similarly to pg_catalog, serving as a logical container that provides views of the DBMS tables we've seen before to abstract their functionality.</p>
<p>The most significant ones are:</p>
<ul>
<li><p><strong>information_schema.tables:</strong> Stores a list of all the tables and views in the database.</p>
</li>
<li><p><strong>information_schema.columns:</strong> Stores metadata for all the columns of all tables and views.</p>
</li>
<li><p><strong>information_schema.table_constraints:</strong> Stores a list of all table-level constraints (primary key, unique, foreign, check...).</p>
</li>
<li><p><strong>information_schema.key_column_usage:</strong> Stores a list of columns involved in key constraints (primary, unique, or foreign).</p>
</li>
<li><p><strong>information_schema.referential_constraints:</strong> Stores metadata about FOREIGN KEY constraints, such as actions triggered after a deletion or update, among others.</p>
</li>
</ul>
<p>To query the information contained in all these tables or views, you can simply use queries as if you were retrieving data from any other user table. But keep in mind that many of them also contain metadata about the DBMS dictionary or catalog tables themselves, which can complicate understanding the results.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> information_schema.<span class="hljs-keyword">tables</span>
<span class="hljs-keyword">WHERE</span> <span class="hljs-built_in">table_name</span>=<span class="hljs-string">'rental'</span>;

<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> pg_catalog.pg_class
<span class="hljs-keyword">WHERE</span> relname = <span class="hljs-string">'bike'</span>;

<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> pg_catalog.pg_stat_activity;

<span class="hljs-comment">/*Get metadata of the PRIMARY KEY constraints we named with "PK"*/</span>
<span class="hljs-keyword">SELECT</span>*
<span class="hljs-keyword">FROM</span> pg_catalog.pg_constraint
<span class="hljs-keyword">WHERE</span> conname <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'%pk%'</span>;

<span class="hljs-keyword">SELECT</span>*
<span class="hljs-keyword">FROM</span> pg_catalog.pg_constraint
<span class="hljs-keyword">WHERE</span> conname <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'%pk%'</span>;

<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> information_schema.table_constraints
<span class="hljs-keyword">WHERE</span> <span class="hljs-built_in">constraint_name</span> <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'%pk%'</span>;
</code></pre>
<h2 id="heading-chapter-10-database-design-process-example">Chapter 10: Database Design Process Example</h2>
<p>So far, you’ve learned about the entire relational model and some basic SQL. Now you can create a relational database on the PostgreSQL DBMS, manage it, and perform queries on it. So let’s apply all this knowledge to a real-world use case.</p>
<h3 id="heading-database-levels">Database Levels</h3>
<p>To do this, we need to remember some of the different levels of the database design process. First, we have the <strong>analysis</strong> phase where we gather the project requirements from the end user or client. Then we create a <strong>conceptual</strong> design, which we subsequently transform into a <strong>logical</strong> design that we can implement on a DBMS.</p>
<p>These are the main levels we need to worry about here. But in addition to these, we have the <strong>physical</strong> level, which focuses on the internal representation of the logical model implementation of the database in the DBMS using DBMS objects like indexes. We also have the <strong>storage</strong> level, which is the closest to the hardware, and is mainly dedicated to organizing the disk files that implement the database functionality on the DBMS. Lastly, we also have the <strong>application</strong> design level that aims to provide the database as a service to the user.</p>
<p>We won’t cover these additional levels in this example due to their complexity and because they aren’t as closely related to the actual database design.</p>
<h3 id="heading-the-database-design-process">The Database Design Process</h3>
<p>When faced with a real problem that requires designing a database, the first thing we need to do is gather as much information as possible from the user or client. We do this to formalize the requirements of the system we’re going to build.</p>
<p>We can interview the client, survey potential users of the service, or use other similar methods. In this case, we won’t directly perform any of these tasks. Instead, we’ll assume that we have certain requirements, and from them we’ve been able to construct an <strong>entity-relationship</strong> diagram that captures them and correctly models the domain of our system. Let’s say it looks like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754234568579/a4165e66-85f1-4a81-b85d-a2be8ea19db3.jpeg" alt="Entity-relationship diagram that we will work with in this chapter. It represents various entities and relationships, where entities include &quot;Vehicle,&quot; &quot;Person,&quot; &quot;Car,&quot; &quot;Pool,&quot; &quot;City,&quot; and others. Image by author. " class="image--center mx-auto" width="1611" height="1405" loading="lazy"></p>
<p>As you can see from the diagram above (you can enlarge it by opening it in a new tab), the project we’ll work on in this example is an extension of the bike rental domain we’ve used so far.</p>
<p>In addition to a bike rental service, we’ll include other elements that may be present in a real world database model, such as vehicles, places, cities, and so on. We’ll also include actions that can be performed between these elements, like owning a car, residing in a city, booking a cruise trip, or getting a bus pass, among others.</p>
<p>When we’re building this diagram, our most significant decisions involve which concepts are modeled with entities, which are represented through relationships, and which aren’t worth including in our system.</p>
<p>From the entire domain, it's common to encounter a lot of information provided by the client or users that doesn't directly help us model the system, as they don’t expect it to be stored in the database. So all concepts related to information that is not intended to be stored <strong>persistently</strong> are usually not included in the design.</p>
<p>As for the other issues, they are very subjective, and there is no set of rules to follow to know unequivocally which concepts to model with <strong>entities</strong> or <strong>relationships</strong> – or even to determine the <strong>degree</strong> of these relationships (which in this context we will assume is always 2 to avoid complicating the design with relationships involving more than two classes).</p>
<h3 id="heading-entity-relationship-to-logical-model">Entity-Relationship to Logical Model</h3>
<p>But to understand how we can and should make these design decisions, it's useful to understand the <strong>purpose</strong> of each entity in this entity-relationship diagram, as well as the meaning of the elements it comprises or relates to. We also need to understand how it’s been translated to the logical design level.</p>
<p>Before explaining each of the entities, below is the relational diagram we have after the entire logical design phase:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1753355497082/c7f6079b-a88b-4651-a92b-36761151aa80.png" alt="Relational diagram derived from the previous entity-relationship one. Image by author. " class="image--center mx-auto" width="6596" height="3794" loading="lazy"></p>
<p>This diagram is what we will gradually build as we transform entities into tables. Make sure you have both this diagram and the entity-relationship diagram open in separate windows so you can refer to them during the following chapters. This will make everything we discuss easier to understand.</p>
<p>As you can see in the diagram above, it includes some modifications like foreign keys pointing to "loose" attributes such as <strong>Sanction.SanctionID</strong>, instead of the same attribute in the table of the diagram. This aims to prevent the foreign key arrows from crossing excessively. Although this isn’t a standard way to represent the relational logical model, as long as its meaning is specified it’s completely valid.</p>
<p>Some constraints aren’t modeled in the system due to their complexity, which we’ll see as we explain all the entities. That's why there are no notes included in the relational diagram, and we don’t indicate the attributes that can or can’t be NULL. These are helpful to show in the diagram, but it’s not required.</p>
<p>Lastly, during the explanations, we’ll show the SQL code used to create each table. You’ll find the SQL script for creating the entire database at the very end, after I’ve explained all the entities. This is because we’re not going to discuss them in the order they need to be created, in order to respect referential integrity constraints that would cause errors in the DBMS if tables were created in a different order.</p>
<h4 id="heading-person-entity">Person entity</h4>
<p>First, we have the entity Person, whose main goal is to model the existence of people in our system. It's important to note that in our domain, there are physical people, where each one is a physical entity that we can abstract through the concept of a person, which has a set of associated characteristics. In other words, even though there are many different people, they all share a set of characteristics that define them as people.</p>
<p>These characteristics are what we’ll model as the attributes of the <strong>Person</strong> entity. These can then be "instantiated," as we saw earlier, resulting in a set of entity occurrences – or in other words, specific people defined by the values of their characteristics or attributes.</p>
<p>To better understand this, we can translate this entity to the logical design level, where, being a single entity, we model it with a single table named Person with the corresponding attributes and data types that match the characteristics of people. In this way, the table schema will be the structure that defines "all people," like a template, while the specific people whose information we want to store in the system correspond to the tuples of the table, which will be inserted as we register people in the system.</p>
<p>For the attributes of the entity, we’ll include those that need to be stored persistently, such as name, date of birth, email, and so on. Among all of them, we choose <strong>PersonID</strong> as the <strong>primary key</strong>, which we assume holds the person's government ID. But to illustrate the concept of <strong>surrogate key</strong> in SQL, in the implementation on the DBMS, we’ll implement the PersonID attribute as a surrogate key instead of the person's actual ID (since both can uniquely identify each person). So each tuple in Person will have a unique and distinct value in that attribute, serving as a superkey, candidate key, and ultimately being selected as the primary key.</p>
<p>In addition to the attributes represented in the entity-relationship diagram, the table we use to model the Person entity has other attributes that help implement associations with other entities, specifically foreign keys.</p>
<p>If we look only at the entity-relationship diagram, we will see a series of associations that "leave" or "enter" the Person entity. In other words, all the relationships this entity has are 1-*, which means the maximum cardinalities on both sides are 1 and *, respectively. These maximum cardinalities tell us how many occurrences of the entities can be related to each other. So with this information, we can determine where to place the foreign keys and which attributes they should reference from specific entities.</p>
<p>In the case of Person, we have 12 associations with such multiplicities, of which only one is a relationship where the <strong>"many"</strong> side (the side with the maximum cardinality *) is in the Person entity itself. This means that to implement the association between Person and <strong>CruiseLine</strong>, for example, at the logical level, there should be a foreign key on the many side pointing to the entity on the 1 side. Otherwise, if we place the foreign key in CruiseLine and have it reference Person, its attribute could contain an arbitrary number of references to people, leading to the appearance of a repeating group.</p>
<p>On the other hand, the other 11 associations have the <strong>"1 side"</strong> in Person, indicating that there are 11 entities that must have a <strong>foreign key</strong> pointing to Person.</p>
<p>Thus, we know that Person has a foreign key pointing to CruiseLine, even though the attributes that make it up do not appear explicitly in the conceptual diagram. And, since the foreign key has to reference tuples from CruiseLine, it will consist of as many attributes as the primary key of CruiseLine, with the same data types, respectively.</p>
<p>This happens because the foreign key must uniquely reference tuples. So the values of the foreign key attributes should allow us to go to the CruiseLine table, look at the columns of its primary key attributes, and easily find the referenced tuple. So the foreign key in Person will have 2 attributes, not just one.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Person (
    PersonID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Birth <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Birth &lt; <span class="hljs-built_in">CURRENT_DATE</span>),
    Email <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Phone <span class="hljs-type">BIGINT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Phone &gt; <span class="hljs-number">0</span>),
    Nationality <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    NameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    FoundationDateFK <span class="hljs-type">DATE</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (NameFK, FoundationDateFK) <span class="hljs-keyword">REFERENCES</span> CruiseLine(<span class="hljs-type">Name</span>, FoundationDate)
);
</code></pre>
<p>Furthermore, as you can see in its DDL, the attributes <strong>(NameFK, FoundationDateFK)</strong> that make up the foreign key don’t have the NOT NULL constraint. This is because the foreign key in Person may not reference any tuple from CruiseLine due to the minimum multiplicity of the association on the CruiseLine side (which, being 0, implies that a person might not be a customer of any cruise line).</p>
<p>Semantically, this association, implemented with the foreign key, represents the possibility that a person can be a customer of a certain cruise line, where if they aren’t a customer of any, their foreign key will be NULL.</p>
<p>At the same time, a cruise line does not necessarily have to have any customers, as it can be related to zero people at a minimum, according to the minimum multiplicity on the other side. So with both minimum multiplicities at 0, the association as a whole becomes optional, meaning it may not exist at all, as there is nothing that requires it to exist.</p>
<p>If we look at the relational diagram, to represent this entity or table, it's enough to write it in <a target="_blank" href="https://en.wikipedia.org/wiki/Datalog"><strong>Datalog</strong></a> notation, with its name and attributes. The only thing to keep in mind is that the attributes that make up the primary key are underlined, and those that represent foreign keys each have an arrow coming from them pointing to the corresponding attribute of the primary key of the entity or table they reference.</p>
<p>In cases like this where the foreign key is composite, each of its attributes has an arrow pointing to the corresponding attribute of the referenced entity. But the order in which the attributes are written in this diagram is not entirely relevant – meaning we can write them in any order as long as we correctly represent which are primary or foreign keys.</p>
<p>Regarding the DDL, since we will consider <strong>PersonID</strong> as a <strong>surrogate key</strong>, we declare it as <a target="_blank" href="https://www.geeksforgeeks.org/postgresql/postgresql-serial/">SERIAL</a> so the column stores <strong>auto-incrementing</strong> values. This way, to uniquely identify each tuple, the attribute will use an integer value that increases by one as tuples are inserted. This allows us to differentiate all of them by that number.</p>
<p>We’ll specify the primary key with <strong>PRIMARY KEY</strong>, which we can place directly in the attribute declaration if it’s not composite. We’ll specify the foreign key with <strong>FOREIGN KEY</strong>, indicating which attributes reference the primary key of CruiseLine.</p>
<p>The only thing to be careful about is the order of the attributes. Although you can arrange the foreign key in any order in FOREIGN KEY, in <strong>REFERENCES</strong>, we must ensure that the attributes of the primary key of CruiseLine are in the same order as those of the foreign key in order to be referenced correctly.</p>
<p>For example, if <strong>NameFK</strong> should reference <strong>Name</strong>, then those attributes will occupy the same position in the tuples where we declare the foreign key and the primary key it points to, without needing to appear in a specific position, as long as the correspondence is maintained.</p>
<p>Now let’s look at what a Person can do.</p>
<h4 id="heading-rental-entity">Rental entity</h4>
<p>In our domain, people can rent bikes, and for each bike rental, we want to store certain information like the time the rental occurred, the duration in hours, the price per hour, and so on. So if we modeled this as an M-N association between <strong>Bike</strong> and <strong>Person</strong>, we couldn't store all this information unless we used an associative entity (which is only valid when the entity itself is weak in identification). But here we prefer to use a surrogate key to uniquely identify the rentals, which avoids making the entity representing them weak in identification.</p>
<p>This is necessary because each rental requires storing associated information, in addition to the person and the bike involved. So an we’ll introduce an entity that relates to both Bike and Person through <strong>1-* associations</strong> (each <strong>Rental</strong> associates a bike with a person), storing information about that "event." Then, as it has two associations with the many side in Rental, this entity will have two foreign keys – one to implement each association. One will reference the primary key of the Bike entity and the other the primary key of the Person entity.</p>
<p>Here, we need to distinguish between both foreign keys, as each is composed of one attribute, unlike the previous case where Person had only one foreign key composed of several attributes. That is, regardless of the attributes that comprise each foreign key, it’s important to distinguish that one aims to uniquely identify a bike while the other uniquely identifies a person.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Rental (
    RentalID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    StartTimestamp <span class="hljs-type">TIMESTAMP</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Duration <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Duration &gt;= <span class="hljs-number">0</span>), <span class="hljs-comment">/*Duration of the rental period in hours*/</span>
    HourPrice <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (HourPrice &gt;= <span class="hljs-number">0</span>),
    BikeFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (BikeFK) <span class="hljs-keyword">REFERENCES</span> Bike(BikeID),
    <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID)
);
</code></pre>
<p>When writing your DDL, the attributes are declared the same as before – the main difference here being that each foreign key has its own FOREIGN KEY constraint, which references the primary key attribute of the corresponding table. This is the case because here, both Bike and Person have primary keys with a single attribute.</p>
<p>Another important detail to consider is the minimum multiplicity on the Person and Bike sides in the associations of the conceptual diagram, where the 1 side of the associations has a minimum multiplicity of 1. This means that a Rental must always be associated with a person and a bike, so their foreign keys can never be NULL. This is why the NOT NULL constraint is used in the attributes.</p>
<p>As before, at the conceptual level, we don’t show the attributes that form the foreign keys, as the associations themselves and their cardinalities implicitly indicate the existence of foreign keys. But in the relational diagram, we do show these attributes, where arrows indicate the primary key attributes of other entities to which they point. And, since the entity is not weak in identification, none of the foreign key attributes should be underlined.</p>
<p>Regarding the other constraints, we don’t allow any attribute to be NULL, as it doesn't make sense for a timestamp to be null, for example, when it’s precisely the valuable information about a rental that we want to store in the database. The other attributes also have constraints like non-negativity, since the duration or the hourly rate can’t be negative amounts.</p>
<p>This way, if someone tries to insert negative values for these attributes, the DBMS will automatically know that the inserted data isn’t valid or correct, since the actual numbers for duration and price can never be negative. This implies that the values for those attributes must be positive to be correct.</p>
<h4 id="heading-carownership-entity">CarOwnership entity</h4>
<p>Another entity related to Person in the diagram – that is, representing something else a Person can do – is <strong>CarOwnership</strong>. This aims to model that people can have cars, whether bought, rented, or leased. For this, we use the same conceptual structure as with Rental, where a person can have multiple cars and a car can belong to many people.</p>
<p>As before, this implicit <strong>N-M association</strong> between <strong>Car</strong> and <strong>Person</strong> must store information about the ownership, such as its type, start date, price, and so on. So we’ll use an intermediate entity with 1-* associations towards both entities, with the 1 side on them.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> CarOwnershipType <span class="hljs-keyword">AS ENUM</span>(<span class="hljs-string">'buy'</span>, <span class="hljs-string">'rental'</span>, <span class="hljs-string">'lease'</span>);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> CarOwnership (
    InsuranceID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    BuyDate <span class="hljs-type">TIMESTAMP</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>, <span class="hljs-comment">/*Date when ownership starts*/</span>
    BuyPrice <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (BuyPrice &gt;= <span class="hljs-number">0</span>), <span class="hljs-comment">/*Ownership price, if rental or lease, this price represents a monthly amount*/</span>
    WarrantyEndDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (WarrantyEndDate &gt;= <span class="hljs-type">DATE</span>(BuyDate)),
    OwnershipType CarOwnershipType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    PlateFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (PlateFK) <span class="hljs-keyword">REFERENCES</span> Car(Plate),
    <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID)
);
</code></pre>
<p>The table implemented at the logical level is very similar to Rental, as we have a surrogate key that uniquely identifies the tuples, thus preventing the entity from being weak in identification. You can see this directly in the conceptual diagram. There, we have an attribute marked with <strong>{id}</strong> that we provide with semantics equivalent to that of a surrogate key. This means we don't need its identification to depend on any other entity.</p>
<p>In other words, at the conceptual level, InsuranceID is a unique identifier provided by an insurance company. To to generate it, they likely used a technique similar to SQL's SERIAL auto-increment, although it doesn't necessarily have to be that, as there are <a target="_blank" href="https://www.freecodecamp.org/news/how-to-effectively-manage-unique-identifiers-at-scale/">many others</a> with very specific applications.</p>
<p>The value of InsuranceID might be provided to us when inserting tuples into our system, where this value would have to meet the primary key constraint and not repeat for any pair of possible tuples. But still, we decided to implement it with a SERIAL to make the generation of synthetic data for this database simpler.</p>
<p>Just keep in mind that, in a real situation, if we are provided with this value, we should avoid using SERIAL and save the identifier that each tuple has. Since InsuranceID is the primary key, no pair of tuples can have the same value in this attribute, but they can have the same start date, price, and so on.</p>
<p>In this table, to restrict the values that the attribute OwnershipType can take, instead of using a CHECK, we’ll create a new data type. We could have done this perfectly using a CREATE DOMAIN. But instead, we’ll use a <a target="_blank" href="https://www.postgresql.org/message-id/49DCDA27.4090901@megafon.hr">TYPE ENUM</a> to show another way of defining the set of values an attribute can take. It defines the possible values for the attribute, representing an ownership where a person buys, rents, or leases a car. Finally, that TYPE ENUM is assigned as the data type of the attribute.</p>
<p>We’ve implemented the most basic domain constraints and problem requirements here, which only involve the <strong>CarOwnership</strong> table itself. For example, we have those requiring the price to be positive or the warranty end date to be after the ownership start date.</p>
<p>On the other hand, we can see that the attribute <strong>BuyDate</strong> has been assigned a <strong>TIMESTAMP</strong> data type, which doesn't exactly match the attribute's name. In this example, such details aren’t as important, since the TIMESTAMP was declared this way to provide a time in addition to the date of purchase. But in a real project, you should be stricter with naming attributes according to their characteristics. This will help improve schema clarity and make database management easier.</p>
<h4 id="heading-residence-entity">Residence entity</h4>
<p>A person can also reside in a city, so our database must be able to store information about a person's stay in a certain city. We’ll do this using the entity Residence, which functions similarly to the previous entities Rental and CarOwnership, but with some differences.</p>
<p>First, the attributes it stores are:</p>
<ul>
<li><p>the start date of a person's stay in a city (which can’t be null because if the stay exists, it must have started on a date),</p>
</li>
<li><p>the end date of the stay (which can be NULL because the person may reside in the city for an indefinite amount of time), and</p>
</li>
<li><p>the address where they reside within the city.</p>
</li>
</ul>
<p>When the EndDate attribute is NULL, it means the person is still residing in the city, as the end date of the stay is not defined. Also, if this date exists and is later than the current date, we can also know that the person still lives in the city until the specified date.</p>
<p>This has implications for identifying the Residence entity, as there is no set of attributes within the entity itself that uniquely identifies the tuples of Residence. Instead, it’s the start date, along with the references to the person and city, that together uniquely identify it. So since the identification of the entity depends on other entities, Residence is a weak entity in terms of identification.</p>
<p>These references work similarly to what we saw earlier in Rental, for example, where we had several 1-* associations with the many side in the Residence entity. This implies that for each association, the foreign key is located in the Residence entity, pointing to the entity on the other side of the association.</p>
<p>Since there are two such associations in total, there are two foreign keys, each formed by one attribute, because the primary keys of the entities they point to are also formed by a single attribute.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Residence (
    StartDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    EndDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">CHECK</span> (
        EndDate <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
        <span class="hljs-keyword">OR</span> EndDate &gt;= StartDate
    ),
    Address <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    CityFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">PRIMARY KEY</span> (StartDate, PersonFK, CityFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID),
    <span class="hljs-keyword">FOREIGN KEY</span> (CityFK) <span class="hljs-keyword">REFERENCES</span> City(CityID)
);
</code></pre>
<p>If we look at the relational diagram, we’ll see that the table implementing this entity has its foreign keys underlined because they’re part of the primary key. This helps us identify that the corresponding conceptual entity is <strong>weak in identification</strong>, with some of its primary key attributes being foreign keys.</p>
<p>Also, if we wanted to reconstruct the conceptual entity from the relational diagram, it would be enough to look at the table's foreign keys, which other entities they reference, whether their attributes are underlined or not, and any possible constraints indicated in the relational diagram.</p>
<p>With this, if any of the foreign keys are underlined, the entity is necessarily <strong>weak</strong> in identification, and the <strong>«weak»</strong> role would be specifically placed on the association modeled by that foreign key. The <strong>many</strong> side of that association would be placed on the side of the entity from which the foreign key originates. And we wouldn’t include its foreign key attributes in the conceptual diagram entity.</p>
<p>In its DDL, we can see that the primary key is composed of StartDate along with the foreign key attributes, where each one represents a different foreign key pointing to a certain entity like Person or City – hence the addition of two FOREIGN KEY constraints. We’ve also added the NOT NULL constraint to both foreign keys due to the minimum multiplicity of the 1 side of the associations, which requires a Residence tuple to relate a person with a city. If we had 0..1 instead of 1..1 on those sides of the associations, then each foreign key of Residence might not reference any person or city, meaning it could be NULL.</p>
<p>Regarding the remaining constraints, no attribute can be null except <strong>EndDate</strong>. If it’s not NULL, then the date it stores must be after the date the residence began, as it wouldn't make sense for it to be earlier than the start date.</p>
<h4 id="heading-shipassignment-entity">ShipAssignment entity</h4>
<p>Another entity that is practically the same as the previous one is ShipAssignment, responsible for modeling the assignment of certain cruise ships to cruise lines. That is, a cruise can belong to or be assigned to a cruise line that operates it under its brand for a certain period, just like a person can reside in a city for a certain period.</p>
<p>Being a weak entity in identification, as we can see in its conceptual diagram, we could have represented it with an associative entity and an N-M association between CruiseShip and CruiseLine. But to be consistent with the notation we used in Residence, we won’t use an associative entity. Instead, we’ll have the entity interpose in the N-M association, resulting in two 1-* associations with the <strong>many</strong> side in ShipAssignment.</p>
<p>This implicitly indicates that there are two foreign keys pointing to CruiseShip and CruiseLine, respectively.</p>
<p>Also, note that just focusing on the <strong>many</strong> side (which is an easy rule to apply to determine where to place foreign keys just by looking at the conceptual diagram) isn’t by itself a good practice without further consideration. When you have a conceptual diagram, you should look at all the elements of the entity to make informed and reasoned decisions about its logical design.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> ShipAssignment (
    StartDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    EndDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (EndDate &gt;= StartDate),
    NameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    FoundationDateFK <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ShipFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">PRIMARY KEY</span> (StartDate, NameFK, FoundationDateFK, ShipFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (NameFK, FoundationDateFK) <span class="hljs-keyword">REFERENCES</span> CruiseLine(<span class="hljs-type">Name</span>, FoundationDate),
    <span class="hljs-keyword">FOREIGN KEY</span> (ShipFK) <span class="hljs-keyword">REFERENCES</span> CruiseShip(ShipID)
);
</code></pre>
<p>Here, we assume the end date of the assignment is always defined, meaning cruises are assigned to cruise lines through "contracts" that always start and end on specific dates, and assignments don’t last indefinitely. This implies that EndDate can never be NULL. So in the DDL, we include the NOT NULL constraint and a CHECK to ensure that EndDate is after the start date, guaranteeing that only valid tuples are inserted into the database.</p>
<p>The foreign keys are formed solely by the attribute ShipFK, which refers to the CruiseShip entity. We use it to reference the cruise assigned to a certain cruise line. But the other foreign key, which is used to implement the other 1-* association, is composed of the attributes <strong>(NameFK, FoundationDateFK)</strong>, which refer to the primary key of CruiseLine – and this, in turn, is composite and contains two attributes <strong>(Name, FoundationDate)</strong>.</p>
<p>If we only look at the relational diagram, we’ll see that three attributes are part of foreign keys because there are arrows coming from them. Specifically, the arrow from one of them (ShipFK) will point to an attribute in a certain table. So we know that this attribute forms a foreign key by itself, while the other two have arrows pointing to attributes of another different entity (but both referencing the same one).</p>
<p>So together, they form another foreign key because the entity or table they reference is <strong>different</strong> from the one referenced by the other attribute <strong>ShipFK</strong>.</p>
<p>These attributes, in turn, serve to uniquely identify each tuple in ShipAssignment – because, with just the start and end dates, we can’t distinguish between any possible pair of tuples.</p>
<p>For example, if several ships are assigned to the same cruise line during the same time period, the start and end dates will match in both tuples, but they’ll represent different assignments even though the dates are the same. So the primary key of the table includes the attributes of the foreign keys, so that their values can distinguish any pair of tuples we might have in the table. Specifically, we include the foreign keys because a cruise can be or have been assigned to several cruise lines, just as a cruise line can have had multiple cruises assigned to it.</p>
<p>The values of both foreign keys are necessary to uniquely identify this "event" between a cruise and a cruise line, because according to the domain, the same cruise can’t be assigned multiple times to the same cruise line on the same date.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">ASSERTION</span> EveryCruiseLineHasAssignment <span class="hljs-keyword">CHECK</span> (
    <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> CruiseLine cl
        <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
                <span class="hljs-keyword">SELECT</span> *
                <span class="hljs-keyword">FROM</span> ShipAssignment sa
                <span class="hljs-keyword">WHERE</span> sa.NameFK = cl.Name
                    <span class="hljs-keyword">AND</span> sa.FoundationDateFK = cl.FoundationDate
            )
    ) 
);
</code></pre>
<p>Lastly, given the minimum multiplicity of 1..* on the ShipAssignment side, we need to implement a constraint to ensure that all cruise lines have at least one cruise assignment, which is always associated with a cruise.</p>
<p>To do this, we can use either an ASSERTION or a TRIGGER, as this is a constraint involving multiple tables. But for simplicity, we’ll assume that the data inserted always meets this constraint. This means we don’t need to include assertions and triggers in the DDL.</p>
<p>Now let’s discuss some other important entities in our system.</p>
<h4 id="heading-city-entity">City entity</h4>
<p>This entity is similar to Person and is used to store information about cities in the system. Specifically, for each city, it stores its name, the country where it’s located, population, area, and coordinates in latitude and longitude. Each physical city in our domain within the system will be represented by a tuple in the City table, which is how we implement this entity at the logical level.</p>
<p>Of all the associations that this entity has, none are of the 1-* type with the <strong>many</strong> side in City. Instead, they all have their 1 side in City. This means there will be exactly 4 foreign keys from other entities pointing to City, but the City table itself won’t have any foreign keys pointing to another entity.</p>
<p>This might not be straightforward to see at the conceptual level, as we need to look at the maximum cardinalities of the associations to know which ones result in foreign keys in the entity we’re implementing.</p>
<p>In contrast, in the relational diagram, this is more direct. References implemented with foreign keys are arrows, so we can directly know how many arrows refer to the primary key of a certain table or how many point to other tables, also clearly indicating from which attributes and tables they originate.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> City (
    CityID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Country <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Population <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Population &gt;= <span class="hljs-number">0</span>),
    Area <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Area &gt;= <span class="hljs-number">0</span>),
    Latitude <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (
        Latitude <span class="hljs-keyword">BETWEEN</span> <span class="hljs-number">-90</span> <span class="hljs-keyword">AND</span> <span class="hljs-number">90</span>
    ),
    Longitude <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (
        Longitude <span class="hljs-keyword">BETWEEN</span> <span class="hljs-number">-180</span> <span class="hljs-keyword">AND</span> <span class="hljs-number">180</span>
    )
);
</code></pre>
<p>Regarding the DDL, we implement the identifier CityID with a <strong>SERIAL</strong> surrogate key, as at the conceptual level we have defined that the attribute <strong>CityID</strong> is the primary key of <strong>City</strong>.</p>
<p>It's important to note that when modeling a domain or solving a problem for a client, we might be required to use identifiers specific to the domain we are modeling, which would mean CityID would be of the same type as the identifier to be stored. But for simplicity, let’s assume that we construct the city identifiers ourselves using a surrogate key.</p>
<p>In addition to the NOT NULL constraints that prevent all attributes from being NULL, since it doesn't make sense for a city to have no name or a defined population number, we impose a restriction on the range of values that Latitude and Longitude can take. This is to ensure the values are valid, even though we can't verify if they are correct, as this mainly depends on the data source.</p>
<p>To do this, we can use the <strong>BETWEEN</strong> operator, which performs the same check as <strong>Latitude &gt;= -90 AND Latitude &lt;= 90</strong> but in a more readable way.</p>
<h4 id="heading-port-entity">Port entity</h4>
<p>In addition to cities, our domain also includes ports, which are represented by the entity Port. Like before, each port will be a tuple in the table, with its primary key composed of the port's name stored in the <strong>Name</strong> attribute and a foreign key that references <strong>City</strong>, modeling the city where the port is located.</p>
<p>We can infer the existence of this foreign key by looking at the entity's associations, where all of them are of the 1-* type, and only one has the <strong>many side</strong> in Port. This precisely models this relationship between Port and City. The others have their <strong>1 side</strong> in Port, indicating that they point to Port, meaning they reference some tuple in the Port table.</p>
<p>At the same time, the foreign key of Port is also part of its primary key because a port can’t be identified by its name alone – we also need to know the city where it’s located.</p>
<p>For example, in this domain, we assume that there can be several ports with the same name, but not located in the same city. So if two ports are in the same city, according to the domain, we have the guarantee that their names can’t be the same. This allows us to define the primary key as the combination <strong>(Name, CityFK)</strong>.</p>
<p>We’re making these assumptions here as an example, but in a real project they would need to be confirmed with domain experts and the client's requirements to ensure they are met. This would allow us to make design decisions such as establishing the keys of an entity. So once we know that Port has a foreign key that is part of its primary key, we know that the entity is weak in identification. In the relational diagram, we will have to underline not only <strong>Name</strong> but also the <strong>CityFK</strong> attribute.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Port (
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    TerminalCount <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (TerminalCount &gt;= <span class="hljs-number">0</span>),
    MaxShipLength <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (MaxShipLength &gt;= <span class="hljs-number">0</span>),
    Area <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Area &gt;= <span class="hljs-number">0</span>),
    CityFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">PRIMARY KEY</span>(<span class="hljs-type">Name</span>, CityFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (CityFK) <span class="hljs-keyword">REFERENCES</span> City(CityID)
);
</code></pre>
<p>The DDL is similar to the previous ones: we have the declaration of attributes and constraints like <strong>PRIMARY KEY</strong>, where the set of attributes <strong>(Name, CityFK)</strong> is defined as those that uniquely identify the tuples of <strong>Port</strong>. We also have the corresponding <strong>FOREIGN KEY</strong> that references the <strong>CityID</strong> attribute, the primary key of the <strong>City</strong> table.</p>
<p>A peculiarity of this CREATE TABLE statement is that we don’t add a NOT NULL constraint to the Name attribute because we don’t need to declare it explicitly in this case. That is, since Name is part of the primary key, and a primary key never allows NULL values in its attributes, we can skip declaring NOT NULL, as PRIMARY KEY does so implicitly to ensure the <a target="_blank" href="https://www.ibm.com/docs/en/db2/11.5.x?topic=concepts-primary-key-referential-integrity-check-unique-constraints"><strong>primary key integrity constraint</strong></a>.</p>
<p>This also applies to the foreign key attribute, which can’t be NULL due to the minimum cardinality (minimum cardinality 1 in 1..1) on the City entity side, which requires all ports to be associated with a city. But to more clearly reflect this minimum cardinality, we add NOT NULL explicitly to the CityFK attribute, even though it’s not strictly necessary.</p>
<p>Lastly, if we want to ensure that the logical design represented in the relational diagram is correct with respect to the conceptual diagram, we can try reconstructing the conceptual entity from the table in the relational diagram.</p>
<p>To do this, after creating the entity with its name and attributes (except for those that are foreign keys), we have to infer the associations implemented through these foreign keys. So for each of them, we introduce an association that relates Port to the entity the foreign key points to, where the many side is on Port and the 1 is on the other entity's side.</p>
<p>In addition to the maximum cardinalities 1 and *, we also have to define the minimums, which we can determine through the constraints indicated in the relational diagram.</p>
<p>For example, if one of the foreign keys can be NULL, then its minimum cardinality on the 1 side of the association will be 0, resulting in that side having a cardinality of 0..1.</p>
<p>On the other hand, if it can’t be NULL, the minimum cardinality is 1. On the other side of the association, we’ll default to a minimum cardinality of 0 unless there are constraints requiring cities to have at least one port, for example. This means the minimum cardinality would be 1, resulting in the Port side of the association having a cardinality of 1..*.</p>
<p>Finally, we can repeat this process with the foreign keys that point to the primary key of Port, leading to more associations with other entities.</p>
<p>For example, if we are reconstructing the conceptual entity <strong>City</strong> from the relational diagram, we will see that there is a foreign key from <strong>Port</strong> pointing to <strong>CityID</strong> of City. So City will have a <strong>1-*</strong> association with <strong>Port</strong>, where the many side is on the Port side because the foreign key originates from Port.</p>
<p>In this way, when we have fully reconstructed the conceptual entity, we’ll determine if it’s weak in identification by checking if any of its foreign keys is underlined. This means it’s also part of the primary key. In that case, we’ll add the role <strong>«weak»</strong> to the associations that have arisen from these foreign keys, always on the side from which the foreign key originates.</p>
<h4 id="heading-cruiseline-entity">CruiseLine entity</h4>
<p>This entity is responsible for representing cruise lines in our system, which can have customers and cruises assigned. Conceptually, this entity is very similar to those we have already seen, as it has a primary key made up of two attributes of the entity itself, and no foreign keys pointing to other entities. But there are foreign keys in other entities that <strong>point</strong> to <strong>CruiseLine</strong>, which we can see from the 1-* type associations.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> CruiseLine (
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    FoundationDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ContactPhone <span class="hljs-type">BIGINT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (ContactPhone &gt; <span class="hljs-number">0</span>),
    Rating <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Rating &gt;= <span class="hljs-number">0</span>),
    <span class="hljs-keyword">PRIMARY KEY</span> (<span class="hljs-type">Name</span>, FoundationDate)
);
</code></pre>
<p>Specifically, the primary key of this entity is made up of the company name and the foundation date. This combination of values might seem unique across the tuples we can store in the table, as it’s very unlikely that multiple cruise lines with the same name would be founded on the same date. But we shouldn’t make these assumptions ourselves – instead, we have to ensure that these conditions are met with the client, target user, or domain experts of our system.</p>
<p>Here, for simplicity, we directly assume that no cruise line has the same name as another founded on the same date, but you should always verify if this holds true in the domain.</p>
<p>So we set <strong>(Name, FoundationDate)</strong> as the primary key, which in turn imposes the implicit NOT NULL constraint on both attributes (meaning we don’t need to declare it explicitly). In the DDL, we can also see that the <strong>ContactPhone</strong> attribute is not of type INTEGER, but <strong>BIGINT</strong>. This is because phone numbers are usually long numbers representing large numeric quantities that would exceed the range representable by a more basic type like INTEGER. For text-type attributes, a fixed maximum length of 32 characters is used for all strings, which is enough to accommodate any cruise line name or similar information.</p>
<p>We could also represent the phone number with a string, allowing the storage of the country code in text format, but this can complicate processing since the number would need to be parsed from text.</p>
<h4 id="heading-vehicle-entity">Vehicle entity</h4>
<p>In our domain, there can be certain types of vehicles, such as cars, cruise ships, bikes, or city buses. They all share a series of <strong>common characteristics</strong> like model, weight, color, or odometer reading to know how far they have traveled since they were manufactured.</p>
<p>These attributes are common to all vehicles in our domain, as they will always have a model name or weight, among other things, regardless of the type of vehicle they are. Becuase of this, we’ve decided to abstract these common characteristics in the conceptual design into a <strong>superclass</strong> entity called <strong>Vehicle</strong>. And from this, all entities representing specific types of vehicles must inherit.</p>
<p>In other words, at a conceptual level, we have an <strong>IS-A hierarchy</strong> where the <strong>parent entity</strong> is <strong>Vehicle</strong>, which contains all the characteristics that define all vehicles. From it, a series of entities inherit that represent specific types of vehicles (where each has more specific characteristics of the corresponding vehicle type).</p>
<p>In summary, we use an IS-A hierarchy because we need to model a situation where a series of "individuals" in our domain share a set of <strong>common features</strong>. Formally, an IS-A hierarchy can be defined as a <a target="_blank" href="https://jcsites.juniata.edu/faculty/rhodes/dbms/eermodel.htm">specialization/generalization</a> relationship between a <strong>superclass</strong> entity and some <strong>inheriting</strong> entities. The inheriting entities are composed of all the characteristics or attributes of the superclass plus some of their own attributes.</p>
<p>But, practically, what matters to us is that a hierarchy allows us to have a superclass (the Vehicle entity in this case) where we have attributes corresponding to these common characteristics, and then a series of entities that inherit from it and represent specific types of individuals (each having specific characteristics depending on their type).</p>
<p>With this, we gain clarity and maintainability in the diagram, as adding a new common characteristic to all vehicles only requires adding it to Vehicle – not to each and every inheriting entity. Similarly, if a new type of vehicle needs to be added to the system, we won’t need to include all the common attributes of vehicles in that entity.</p>
<h4 id="heading-how-is-this-is-a-hierarchy-implemented-with-tables">How is this IS-A hierarchy implemented with tables?</h4>
<p>At this point, we need to decide how to implement the hierarchy using tables in the logical model. Specifically, we have to determine the number of tables to use and the keys each will have concerning the implementation of the hierarchy itself.</p>
<p>To start, it's important to see that Vehicle has VehicleID as its primary key, which we assume is a surrogate key. With this, we know that if we had to implement any table for the inheriting entities, they should have a foreign key pointing to VehicleID, as it’s the primary key that can uniquely identify tuples of Vehicle.</p>
<p>We see that the hierarchy here is <strong>complete</strong> and <strong>disjoint</strong>. It’s complete because all the "individuals" in the hierarchy must always be represented by the inheriting entities. In other words, we will never find a vehicle that only has the attributes of Vehicle – instead, all vehicles in our domain are necessarily of one of the types defined in the inheriting entities (or so we assume). It’s <strong>disjoint</strong> because a vehicle can’t be of multiple types at once, meaning it can’t be both a car and a cruise ship, which makes sense.</p>
<p>All this means that each of them will be implemented with a specific table. Our system stores many types of vehicles and will likely need to expand with even more types of vehicles. To simplify this process of adding new types of vehicles and to avoid the appearance of too many NULL values in tables, we’ll implement a table for each inheriting entity of the hierarchy.</p>
<p>For the superclass, we’ll also implement a specific table, as each vehicle that exists in our system will be represented in one of the tables of the inheriting entities – but it’ll need to take values in the characteristics (attributes) of the superclass.</p>
<p>Here, we have several options. One option is not to implement a table for the superclass, duplicating all its attributes in each of the tables of the inheriting entities. This is easy to understand and initially seems practical, but it has significant drawbacks.</p>
<p>Another option is to implement a table for the superclass and include a foreign key in all the inheriting entities that point to the primary key of Vehicle.</p>
<p>We can easily dismiss the first option because duplicating attributes in all the tables for different types of vehicles leads to a lot of <a target="_blank" href="https://softwareengineering.stackexchange.com/questions/227832/single-table-w-extra-columns-vs-multiple-tables-which-duplicate-schema?utm_source=chatgpt.com">redundancy at the metadata level</a> or <strong>schema</strong>, meaning duplicated attributes in multiple tables without a clear need for duplication.</p>
<p>Beyond the redundancy issue, duplicating the same attributes in multiple tables makes certain schema modifications more complicated. For example, adding an additional common feature in Vehicle would require adding an attribute in each table. Or we could change how common attributes like <strong>color</strong> are represented, such as switching color names from uppercase to lowercase (or any change in their representation). We’d need to make these changes across all the vehicle type tables.</p>
<p>With the other option, we implement a specific table for the superclass, avoiding these problems by centralizing the storage of common features in a single table. This makes it easier to perform the operations mentioned before, or even additional ones like counting how many vehicles are in our system.</p>
<p>We can easily do this by counting the tuples in the Vehicle table, instead of adding up the tuple counts from each of the tables for different types of vehicles. We can resolve this query this way because all vehicles will have a <strong>tuple in Vehicle</strong> that stores the common features, as well as one in their specific vehicle type table that stores the rest of the features defining it as a car, cruise, bike, and so on.</p>
<p>In this tuple, there’s a <strong>foreign key</strong> that references the tuple in the superclass table, thus associating the information from both tuples so it can query it and know all the information about a vehicle – both its <strong>common</strong> features to all vehicles and the <strong>specific</strong> ones of its type.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> ColorType <span class="hljs-keyword">AS ENUM</span> ( <span class="hljs-string">'red'</span>, <span class="hljs-string">'green'</span>, <span class="hljs-string">'blue'</span>, <span class="hljs-string">'yellow'</span>, <span class="hljs-string">'black'</span>, <span class="hljs-string">'white'</span> ); 
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Vehicle (
    VehicleID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    Model <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Weight <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Weight &gt;= <span class="hljs-number">0</span>),
    Color ColorType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Odometer <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Odometer &gt;= <span class="hljs-number">0</span>)
);
</code></pre>
<p>Finally, we decide to implement a table for all entities in the hierarchy, using <strong>foreign keys</strong> in the tables of the inheriting entities to reference tuples in Vehicle that store the common features of the vehicles.</p>
<p>In its DDL, we can see that the primary key is implemented with an attribute of type <strong>SERIAL</strong> because it’s a <strong>surrogate key</strong>. For the <strong>Color</strong> attribute, we create a <strong>TYPE ENUM</strong> with the possible colors in our system. This is a good practice because if we need a color attribute in more areas of the system, we’ll have its domain (or data type) defined in <strong>ColorType</strong>. And this allows us to reuse it and ensure that all color attributes can take values from exactly the same data set.</p>
<p>But if we try to reconstruct the IS-A hierarchy from the entity-relationship diagram just by looking at the implementation represented in the relational diagram, we’ll realize that it’s somewhat more complex than what we saw before.</p>
<p>This is because there’s not a single way to translate an IS-A hierarchy into a relational diagram. Depending on the semantics of the features and entities, plus the system requirements, it may be better to use more or fewer tables to implement it. But in cases like this where we have a table for each entity in the hierarchy, we can clearly see that there’s a Vehicle table with a primary key VehicleID (which is referenced by multiple tables, each having exactly the same foreign key referencing Vehicle).</p>
<p>If we only look at this, we might think that Vehicle is an entity that has 1-* associations with other entities – and this is entirely possible when looking only at the relational diagram.</p>
<p>But to derive the conceptual design from the logical one and infer the existence of an IS-A hierarchy, we have to focus on the semantics of the tables and attributes. That's where we'll see that Vehicle contains attributes common to all types of vehicles that have foreign keys pointing to Vehicle. This gives us clues that Vehicle could be the superclass of a hierarchy, and the rest of the tables with foreign keys pointing to Vehicle could be inheriting entities.</p>
<p>But inferring the existence of an IS-A hierarchy in the conceptual design simply by observing the logical implementation is not always unequivocal. This is because, for example, here we could perfectly consider that Vehicle is an entity associated with the other inheriting entities through 1-* type associations. This would also be correct from a conceptual and logical point of view.</p>
<p>Still, even though conceptually we can transform the hierarchy into a series of 1-* associations between Vehicle and the other entities, this is only true to the implementation if we implement one table per entity. Otherwise, we wouldn’t be correctly reflecting in the conceptual design what is actually implemented in the logical one.</p>
<p>In summary, when we see an IS-A hierarchy, it doesn't necessarily mean there are foreign keys between the inheriting entities and the superclass, as not always as many tables as entities are used to implement the hierarchy. So to reconstruct a hierarchy at the conceptual level from the logical one, the most reliable thing to focus on is the constraints, notes, or indications left in the relational diagram explaining why certain tables were implemented – that is, where they come from.</p>
<p>Implementing a hierarchy at the logical level usually involves a series of design decisions that must be properly justified, which we can then use to infer the existence of the hierarchy at the conceptual level.</p>
<p>This exercise of trying to reconstruct the conceptual level is important to approach clearly, as understanding this reverse process is key to comprehending the elements of the different design levels and how they translate from one to another.</p>
<h4 id="heading-cruiseship-entity">CruiseShip entity</h4>
<p>To illustrate how we’ve implemented the IS-A hierarchy of Vehicle, let's look at the different inheriting entities that make it up.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754729845339/090a3c2f-0833-4f14-8a58-52fb1a1606ea.png" alt="Part of the entity-relationship diagram where the IS-A hierarchy of vehicles is represented according to their type. Image by author. " class="image--center mx-auto" width="1614" height="383" loading="lazy"></p>
<p>First, we have CruiseShip, which models the existence of cruise ship-type vehicles in our system, where each cruise ship is a tuple in the table. Regarding the specific features of the cruise ship that make it a cruise ship-type vehicle, we have its length, passenger capacity, or even the speed at which it travels. It also has features that all vehicles must have in the Vehicle table, such as model, color, and so on, specifically in tuples that store the values of each cruise's features.</p>
<p>To relate this information from both tables, there is a foreign key in CruiseShip that points to Vehicle, meaning it references the tuple in Vehicle where these feature values are stored, for each cruise ship (tuple of CruiseShip).</p>
<p>This way, we ensure that the attributes repeated in all vehicle types are centralized in one table where they can be easily modified or consulted, much better than having them all duplicated in the different tables of vehicle types.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> ClassType <span class="hljs-keyword">AS ENUM</span>(<span class="hljs-string">'first'</span>, <span class="hljs-string">'second'</span>, <span class="hljs-string">'third'</span>, <span class="hljs-string">'economy'</span>);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> CruiseShip (
    ShipID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    Speed <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Speed &gt;= <span class="hljs-number">0</span>),
    Length <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Length &gt;= <span class="hljs-number">0</span>),
    PassengerCapacity <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (PassengerCapacity &gt;= <span class="hljs-number">0</span>),
    <span class="hljs-keyword">Class</span> ClassType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    VehicleID <span class="hljs-type">INT</span> <span class="hljs-keyword">UNIQUE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (VehicleID) <span class="hljs-keyword">REFERENCES</span> Vehicle(VehicleID)
);
</code></pre>
<p>In the DDL, we see that the attributes and their types are declared, where ShipID is defined as a surrogate key using the SERIAL data type. This allows us to uniquely identify each cruise ship. But since every cruise ship is also a vehicle, we could also identify it by making its primary key <strong>{VehicleID}</strong>, because this attribute, even though it’s a foreign key, will never be NULL since a cruise ship needs to have the features that classify it as a vehicle.</p>
<p>So the foreign key must reference a valid tuple in Vehicle where the values for the features common to all vehicles are stored. Consequently, VehicleID is an alternative key declared with the UNIQUE constraint, although we aren’t required to add this constraint since the surrogate key ShipID is sufficient to identify it.</p>
<p>The important thing about this attribute is to correctly define the NOT NULL and FOREIGN KEY constraints, ensuring it correctly references the primary key VehicleID of the Vehicle table.</p>
<p>In the conceptual design, we see that this entity has multiple 1-* associations, which indicate that there are three foreign keys from other entities pointing to CruiseShip. But if we only have the conceptual design, we can’t say anything about the possible foreign key generated by the IS-A hierarchy. That is, if we only have the conceptual diagram, we can’t "guess" how many tables have been used to implement the hierarchy – we only know that after creating the logical design. At most, we could consider all possible options for implementing the hierarchy and, for each one, analyze whether there is a foreign key coming from CruiseShip.</p>
<p>But if in addition to the entity-relationship diagram we know that there is a foreign key originating from CruiseShip and pointing to another entity, then the entity it points to must necessarily be Vehicle. This is because 1-* type associations are elements that we know will generate foreign keys. But certain types of associations like 1-1 or 0..1-0..1 can lead to ambiguities, as we have seen before when trying to infer the existence of a hierarchy at the conceptual level.</p>
<p>So by discarding entities related through 1-* associations, the only option left would be Vehicle. With all this, we can also know that the implementation of the hierarchy at the logical level has been done by creating a table for the superclass and for the CruiseShip entity – but we couldn’t be sure whether the other entities have also been implemented with a table or not, as that heavily depends on the semantics.</p>
<h4 id="heading-bike-entity">Bike entity</h4>
<p>Continuing with the different types of vehicles, we also have bicycles represented in the entity Bike, which inherits from Vehicle. Here, it’s clearer that the attributes of the inheriting entities are more specific than those of the superclass, as only bikes have features like FrameHeight or Foldable.</p>
<p>If we only look at the conceptual diagram, we can’t be certain if Bike has a foreign key pointing to Vehicle. This is precisely because, as mentioned before, without knowing the specific implementation at the logical level, we can’t guarantee that there is a foreign key in Bike. But considering the semantics of the hierarchy, we could propose the different options available for implementing it and determine in each case whether such a foreign key exists.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Bike (
    BikeID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    Electric <span class="hljs-type">BOOLEAN</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Foldable <span class="hljs-type">BOOLEAN</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    HasLights <span class="hljs-type">BOOLEAN</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    FrameHeight <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (FrameHeight &gt;= <span class="hljs-number">0</span>),
    VehicleID <span class="hljs-type">INT</span> <span class="hljs-keyword">UNIQUE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (VehicleID) <span class="hljs-keyword">REFERENCES</span> Vehicle(VehicleID)
);
</code></pre>
<p>Since we decided to use a table to implement each table in the hierarchy, in this case, there is indeed such a foreign key, just as in <strong>CruiseShip</strong>. And we can see it declared in the same way as the FOREIGN KEY constraint.</p>
<p>Also, the primary key of Bike is not the foreign key that uniquely identifies the vehicles. Instead, it’s the <strong>BikeID</strong> identifier. Here we’re assuming that our domain requires each type of vehicle to have its own identifier. That is, in addition to the VehicleID identifier that serves for any type of vehicle, each of these types must have its own <strong>type-specific identifier</strong>. This means that cruise ships, bikes, cars, and buses will each have a way to identify themselves (even though all of them can be distinguished from each other by the <strong>VehicleID</strong> identifier they possess indirectly through their foreign key referencing Vehicle. This is why the foreign key attribute is declared as UNIQUE.).</p>
<p>And since this foreign key is not part of the primary key, the entity is not weak in identification. Even if it were, it wouldn’t be marked in any way at the conceptual level. This is because at that level, we have a hierarchy of entities that can be implemented at the logical level in many ways, and not all of them will have entities weak in identification.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752833986569/a77fb4b1-3632-4d63-ad28-750c6768ef0d.png" alt="Entity-relationship diagram with inheritance where Bike and Car are subclasses of Vehicle. Image by author. " class="image--center mx-auto" width="1004" height="423" loading="lazy"></p>
<p>To understand this, we can consider a simpler example of a hierarchy with only two inheriting entities (as you can see in the diagram above). If we only have the conceptual design, we still won't know which tables we'll use to implement the hierarchy – although we know we have several options, such as:</p>
<ul>
<li><p>implementing or not implementing a table for the superclass</p>
</li>
<li><p>implementing a table to represent all inheriting entities, or just one table for each entity</p>
</li>
<li><p>or even more complex implementations like using a single table for the superclass and some of the inheriting entities.</p>
</li>
</ul>
<p>Each of these options has its peculiarities. If we don't implement a table for the superclass, then there will necessarily be no foreign keys pointing to it. Or if we decide to create a table to represent the superclass and some inheriting entity together, then that inheriting entity won’t have any foreign key pointing to the superclass.</p>
<p>Regarding weakness in identification, depending on whether we are required to have each type of vehicle with its own identifier, we could have a global identifier in the superclass, or as in our diagram, multiple identifiers, one for each type of vehicle in addition to the Vehicle superclass identifier that identifies any vehicle. So we see that weakness in identification does not always exist, as it mainly depends on the domain and the requirements of the problem.</p>
<p>For example, if we see identifiers in each of the inheriting entities, and we know that those identifiers can serve as primary keys, then this suggests that the inheriting entities may have been implemented with a table each, where their foreign key initially does not include other foreign key attributes. But the conceptual diagram can’t guarantee this, as the existence or absence of a foreign key that may or may not be part of the primary key when implementing a hierarchy is a design decision specific to the logical level.</p>
<p>Another aspect we can infer from the conceptual diagram is the 1-* associations where the 1 is in one of the entities of the hierarchy. Necessarily, if any foreign key points to the superclass (the 1 side of the association is in the superclass), then a table must be implemented for it.</p>
<p>On the other hand, if it points to one of the inheriting entities, it’s not a sufficient condition to infer that there is a table for that inheriting entity. This is because there may be a table representing the superclass along with that inheriting entity, with the foreign key perfectly pointing to the identifier of that table.</p>
<p>So in the IS-A hierarchies of the conceptual model, the "weak" role is never used to indicate possible identification weakness that the tables implementing the entities might have. There are many ways to implement the hierarchy with tables, and the chosen method is not 100% determined by the conceptual diagram.</p>
<p>But it’s very important to be clear that the entities in the hierarchy can have associations with other entities that make them weak in identification. In that case, even though they are part of an IS-A hierarchy, the "weak" role would be used to indicate that the entity is weak in identification (but not due to the hierarchy – rather because of an association with another entity).</p>
<h4 id="heading-car-entity">Car entity</h4>
<p>Similar to the previous entities, we have Car, which represents the existence of cars in the system. Its primary key is Plate, which we assume is unique for each car. As we can see in the DDL, the data type of Plate is VARCHAR. This makes it perfectly possible for the attribute to be part of a primary key, as they don’t necessarily have to be integers or numeric to be part of a key. Any data type whose values are unique across the tuples stored in the table can serve.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> CarFuelType <span class="hljs-keyword">AS ENUM</span> ( <span class="hljs-string">'gas'</span>, <span class="hljs-string">'diesel'</span>, <span class="hljs-string">'electric'</span>, <span class="hljs-string">'hybrid'</span>, <span class="hljs-string">'hydrogen'</span> ); 
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Car (
    Plate <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">PRIMARY KEY</span>,
    FuelType CarFuelType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    DoorCount <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (DoorCount &gt;= <span class="hljs-number">0</span>),
    TrunkCapacity <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (TrunkCapacity &gt;= <span class="hljs-number">0</span>),
    HorsePower <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (HorsePower &gt;= <span class="hljs-number">0</span>),
    Doors <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Doors &gt; <span class="hljs-number">0</span>),
    AirConditioning <span class="hljs-type">BOOLEAN</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    VehicleID <span class="hljs-type">INT</span> <span class="hljs-keyword">UNIQUE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (VehicleID) <span class="hljs-keyword">REFERENCES</span> Vehicle(VehicleID)
);
</code></pre>
<p>Regarding the foreign keys related to this entity, we have the same one as before, which serves to reference a tuple of Vehicle that stores information about the car model, color, and so on. But looking at the conceptual diagram, we can see that there are two other foreign keys in other entities pointing to Car, since the 1 side of the corresponding 1-* associations is in Car.</p>
<p>Even though we can’t see this in the DDL of the Car table, these foreign keys are in other entities referencing Car. But we can see them in the relational diagram as arrows pointing to the attributes of the primary key of Car.</p>
<p>Lastly, we also create an ENUM TYPE to restrict the domain of the FuelType attribute. We could implement this perfectly with a constraint, but to reuse this data type in other entities that might need it, we should define a DOMAIN or an ENUM TYPE (as in this case, that can be assigned as a data type to the attribute).</p>
<p>Also, defining a set of values this way is especially useful when the attribute holds text, as in other numeric attributes it may be easier to restrict their possible values with conditions like (HorsePower &gt;= 0).</p>
<h4 id="heading-citybus-entity">CityBus entity</h4>
<p>To finish with the vehicle hierarchy, we have CityBus, which represents city buses in our domain. In this entity, we also have Plate as the primary key, which stores the bus's license plate and serves to uniquely identify it (meaning it differentiates it from any other city bus).</p>
<p>But the license plate does not directly differentiate it from other types of vehicles like cars or bikes, as the semantics of each attribute are different for each type of vehicle, as mentioned before.</p>
<p>For example, although cars and buses both have a license plate, if we try to differentiate cars from buses using their Plate attributes, we will see that cars may have a different license plate structure than buses, as determined by the domain and project requirements.</p>
<p>So to distinguish and uniquely identify them, we need to use the VehicleID identifier, since Plate is specific to the vehicle types Car and CityBus.</p>
<p>In addition to representing the existence of buses, this entity has 1-* type associations with Person and City that model the person driving each bus and the city where it operates. So in the conceptual diagram, we can see that the association with Person has the role <strong>“drives”</strong>. This indicates that a person can drive an arbitrary number of buses, while a bus is driven by one and only one person.</p>
<p>This association results in <strong>CityBus</strong> having a foreign key pointing to Person, allowing us to know, given a bus, the person who drives it by accessing the Person tuple referenced by the foreign key attribute.</p>
<p>Similarly, CityBus also has an association with City that represents the city to which each bus belongs and operates. Conceptually, we can see this as each bus having to operate in only one city, and each city having an arbitrary number of buses operating in it, including none (since the minimum cardinality on the CityBus side is 0).</p>
<p>Logically, this is implemented with a foreign key in CityBus pointing to City. So if we need to know the city where a certain bus operates, we simply check the value of its foreign key, which will uniquely identify a tuple in City, indicating the city we are looking for.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> CityBus (
    Plate <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">PRIMARY KEY</span>,
    RouteNumber <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (RouteNumber &gt;= <span class="hljs-number">0</span>),
    Seats <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Seats &gt; <span class="hljs-number">0</span>),
    FreeWifi <span class="hljs-type">BOOLEAN</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    VehicleID <span class="hljs-type">INT</span> <span class="hljs-keyword">UNIQUE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    DriverFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    CityFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (VehicleID) <span class="hljs-keyword">REFERENCES</span> Vehicle(VehicleID),
    <span class="hljs-keyword">FOREIGN KEY</span> (DriverFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID),
    <span class="hljs-keyword">FOREIGN KEY</span> (CityFK) <span class="hljs-keyword">REFERENCES</span> City(CityID)
);
</code></pre>
<p>In addition to the previous foreign keys, there is another one in the BusTrip entity that references CityBus, which we can see with the 1-* type association it has with that entity. This last one isn’t directly reflected in the DDL of CityBus, but it’s in the relational diagram where we have an arrow pointing to the primary key Plate. And, as usual, we do not add the NOT NULL constraint to the Plate attribute, since we are imposing the PRIMARY KEY constraint, which implicitly includes NOT NULL in all the attributes that comprise it.</p>
<p>The foreign keys for Person and City also can’t be NULL due to the minimum cardinalities of the associations, where having 1..1 implies that a city bus must have a driver and a city to operate in, hence NOT NULL is explicitly added in the DDL.</p>
<h4 id="heading-carregistration-entity">CarRegistration entity</h4>
<p>In our domain, cars can belong to a person through a record in the Carownership table. They can also be registered as fit to drive through CarRegistration, which associates cars with driver's licenses to model their legal registration. That is, a car can exist at any time, but to be able to drive, it must be registered and associated with a driver's license. This is why CarRegistration is dedicated to associating cars with driver's licenses.</p>
<p>The entity is very similar to some we have seen before, like Residence (while the entities it relates to here are different, as well as the reason for its existence). Implicitly, a car can be registered and associated with many driver's licenses, while the same driver's license can have an arbitrary number of cars associated with it. We can determine this by observing the <strong>cardinalities</strong> and <strong>navigability</strong> of the associations in the conceptual diagram.</p>
<p>For example, if we have a car, then by conducting an exhaustive search in the tuples of CarRegistration, we can find out how many records it’s in or has participated in. Also, for each of those records, we automatically know the driver's license it has been associated with – so from one car, we can learn about many driver's licenses.</p>
<p>Conversely, the same applies: if we have a certain license, we can indirectly find out by looking in the CarRegistration table how many records associate cars with that license. And for each of those records, we would obtain the associated car.</p>
<p>We’ve now analyzed navigability at the logical level. Previously, we saw the concept of navigability at the conceptual level, where associations could only be traversed in a certain direction depending on their cardinality. But in the logical model, we have access to all the tuples of all the tables in the database schema.</p>
<p>So, even though the Car-CarRegistration association is not navigable towards CarRegistration at the conceptual level, it is at the logical level. That is, if we have a car, we can find out which tuples in CarRegistration refer to that car, using the foreign keys that implement the association. With that information, we can then navigate to DrivingLicense once we know which tuples in CarRegistration pointed to the car.</p>
<p>This type of navigation is considered more typical of the logical level. With it, we can obtain information from other entities in a broader way than with the concept of navigation we saw at the conceptual level.</p>
<p>Here, on the <strong>entity-relationship diagram</strong>, we can see that there is an implicit N-M association between Car and DrivingLicense, which we just navigated through.</p>
<p>To do this, we had to go through the 1-* type associations, which are divided so that there can be an "intermediate" entity that stores information related to the N-M association, and to enable its implementation at the logical level. But we need to keep in mind the cardinalities of the 1-* associations that make up the implicit N-M association, where on the CarRegistration side we have optionality because the minimum cardinality is 0. This means that a car may not be registered, so there would be no tuple in CarRegistration referring to a certain car, thus preventing navigation to DrivingLicense.</p>
<p>This is completely valid because if a car is not registered, it won’t be associated with any driving license, and so we won’t be able to access any information from DrivingLicense.</p>
<p>Despite this, since there is a possibility that it’s registered, we consider these associations at the logical level to be navigable (all of this is equivalent to analyzing it in the opposite direction, from DrivingLicense to Car through CarRegistration).</p>
<p>For this process to be carried out, CarRegistration needs to have two foreign keys: one pointing to the primary key of Car to uniquely identify the car being registered, and another pointing to DrivingLicense to identify the driver's license associated with the car.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> CarRegistration (
    RegistrationID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    RegistrationDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ExpirationDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (ExpirationDate &gt; RegistrationDate),
    PlateFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    LicenseFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (PlateFK) <span class="hljs-keyword">REFERENCES</span> Car(Plate),
    <span class="hljs-keyword">FOREIGN KEY</span> (LicenseFK) <span class="hljs-keyword">REFERENCES</span> DrivingLicense(LicenseID)
);
</code></pre>
<p>When implementing the CarRegistration table, we see in its DDL that the primary key is declared as SERIAL because it’s a surrogate key. Also, the foreign keys all have the NOT NULL constraint due to the minimum multiplicity of 1 for the corresponding associations, which requires every tuple in CarRegistration to reference exactly one car and one driving license.</p>
<p>Regarding the information stored in the car registration, we mainly have the registration date or expiration date. Neither can be NULL, since we assume that in our domain, cars are always registered for a certain period that can later be extended through other registrations.</p>
<p>Here, we could have defined the CarRegistration entity as weak in identification, including both foreign keys in a primary key like <strong>{RegistrationDate, PlateFK, LicenseFK}</strong>. But for simplicity, a surrogate key is preferred, which simplifies database operations. In fact, the only advantage of not using the surrogate key would be saving the space occupied by the values of that additional column (and we could remove it if need be). But doing so would complicate the identification of CarRegistration tuples, as well as make certain queries less efficient and less readable.</p>
<p>And if we delve into the physical level, we would realize that having a primary key composed of more attributes would cause the DBMS to use more space to manage it. This would counteract the savings from removing the surrogate key – so the surrogate key remains the preferred option.</p>
<p>In summary, at the conceptual level, we’ve learned that navigation from Car to DrivingLicense is not entirely possible, as there is no foreign key in Car pointing to CarRegistration. But at the logical level, we can get information from CarRegistration because we can examine all the tuples of CarRegistration, allowing us to know which of them has their corresponding foreign key referencing the car we started from.</p>
<p>That is, conceptually, 1-* type associations are only navigable from the many side to the one side, but at the logical level, they are considered bidirectional. Also, the 1-* associations surrounding CarRegistration are both of the 1-* type and implicitly give rise to an N-M type, which is another reason why we can actually navigate from Car to DrivingLicense through CarRegistration.</p>
<h4 id="heading-drivinglicenserequest-entity">DrivingLicenseRequest entity</h4>
<p>In our domain, people can request a driver's license from a public entity, which in this case doesn't matter to us – we only care that it’s responsible for accepting or rejecting these requests. If a request is accepted, it should become the driver's license of the person who requested it, while if it is rejected, it will remain in the database as a failed request.</p>
<p>To model this in our database, we have many options:</p>
<ul>
<li><p>creating a <strong>DrivingLicenseRequest</strong> entity with a boolean attribute <strong>Accepted</strong> to represent whether the request status is accepted or not, or</p>
</li>
<li><p>creating an IS-A hierarchy as seen in the conceptual diagram, where we have a superclass <strong>DrivingLicenseRequest</strong> dedicated to recording all requests that exist or have existed. In turn, we have inheriting entities that are created once the request has been resolved, with one entity representing accepted requests and the other modeling those that are rejected.</p>
</li>
</ul>
<p>On one hand, using a single entity with attributes that determine its status is not the best option, because besides knowing if it has been rejected or not, the request can be in process. This would mean that it’s neither accepted nor rejected yet.</p>
<p>This causes multiple problems that complicate implementation, such as needing to make the Accepted attribute NULL until the request has been resolved, or even using this NULL value to represent the request's status. This "mixes" the semantics of the Accepted attribute with the representation of the request's status. This is not necessarily a serious problem, just a lack of clarity in representing the status and outcome of a request.</p>
<p>This option would also generate NULL values in the <strong>specific attributes</strong> of rejected or accepted requests, since each of them requires specific attributes that the other type does not have (such as the <strong>number of points</strong> for an accepted driver's license). So with this option, besides distinguishing the type of request, you would need to manage the NULL values in all attributes that don’t correspond with the type represented in the <strong>Accepted</strong> attribute. And this greatly complicates the semantics and operations when managing the data, as well as wasting unnecessary space storing these NULLs.</p>
<p>On the other hand, using an IS-A hierarchy to conceptually model driver's license requests can bring other disadvantages, such as greater complexity in the schema from the high number of tables that can be generated. You can also have more complexity when adding constraints to ensure that a request is not accepted and rejected at the same time. Or you can even have data fragmentation across multiple tables, where part of the information is stored in a superclass and the rest in an entity representing the specific type of request, whether accepted or rejected.</p>
<p>Still, using an IS-A hierarchy solves all the problems we saw with the previous option, providing a simpler and more consistent semantics with which we can operate on the database more easily. It also keeps us from having to worry about managing NULL values in certain attributes or the consistency between attributes that determine the request's status, as there are none of those here.</p>
<p>Thus, in the conceptual model, we have an IS-A hierarchy representing these requests, where a superclass represents requests that have just been created and are in process. In inheriting entities, these same requests are represented once they have been resolved. If they are rejected, they become a specific type <strong>RejectedDrivingLicense</strong>, and if accepted, another type called simply <strong>DrivingLicense</strong>.</p>
<p>In other words, at the conceptual level, we can view each request as an "individual" that can be found in the set of entity occurrences of the superclass, indicating that the request is in process. When it’s rejected or accepted, that individual then belongs to the set of the corresponding inheriting entity.</p>
<h4 id="heading-how-can-we-model-the-driving-license-requests-hierarchy-at-the-logical-level">How can we model the driving license requests hierarchy at the logical level?</h4>
<p>As we have seen before, an IS-A hierarchy doesn’t have a direct and unique translation at the logical level, as its semantics and domain requirements determine which possibilities are better or worse in aspects like query efficiency, ease of management, and so on.</p>
<p>So to translate this entity hierarchy formed by the superclass entity <strong>DrivingLicenseRequest</strong> and the inheriting entities <strong>RejectedDrivingLicense</strong> and <strong>DrivingLicense</strong> into tables in a DBMS, we need to analyze its characteristics to determine what implementation best suits the domain we’re modeling. We also need to analyze the other entities and the associations that connect with them, such as the association between Person and DrivingLicense, which models the relationship between a person and their driving license.</p>
<p>The first thing we need to check is whether the hierarchy is complete or not. In this case, there can be requests in process that haven’t been accepted or rejected, and so aren’t represented in any of the inheriting entities.</p>
<p>Since there are requests that don’t necessarily need to be represented by any inheriting entity, we see that the hierarchy is <strong>not complete (partial)</strong>. Given that it’s not complete, the only way for our database to correctly store those requests that are in process is to create a specific table for the superclass DrivingLicenseRequest. Without it, it would be more complicated to know when a request has been resolved or not.</p>
<p>Later, knowing that all requests are stored in DrivingLicenseRequest, our system must be able to store information that determines whether it has been resolved or not, as well as the result of its resolution. For this, when a request is resolved and accepted, an occurrence of the entity DrivingLicense is created. But if it’s rejected, an occurrence of the other inheriting entity is created.</p>
<p>So in no case will the request be represented by occurrences of multiple inheriting entities at the same time, so the hierarchy is <strong>disjoint</strong>. This ensures that the previous decision to implement a table for the superclass is the correct option.</p>
<p>To translate the inheriting entities to the logical level, we need to decide whether to implement a table for each one, a single table for both, or even a table with all the entities in the hierarchy.</p>
<p>The most important thing to consider in this decision is the number of attributes each entity has and the tuples expected to exist in the database if we implement a table for each entity. In other words, we need to consider how many occurrences of each entity are expected to exist in the domain.</p>
<p>Initially, we can assume that there are always more rejected licenses than accepted ones, as it’s very likely to be rejected at least once before being accepted. With this, we could decide to implement a table for the <strong>DrivingLicenseRequest</strong> and <strong>RejectedDrivingLicense</strong> entities together (since there are more rejected than accepted) and another for DrivingLicense that has a <strong>foreign key</strong> pointing to that table. But this would generate NULL values in the attributes from RejectedDrivingLicense when representing accepted driving licenses.</p>
<p>Since implementing the entire hierarchy with a single table also leads to too many NULL values in the attributes when representing accepted or rejected licenses, the best solution in this case is again to implement a table for each entity in the hierarchy.</p>
<p>The main reason for choosing this option is the number of NULL values generated when representing accepted or rejected licenses. In general, if the inheriting entities had only one attribute, then it would be clear that it could be implemented more simply with a single table for the entire hierarchy, or two.</p>
<p>But when there is more than one attribute, the queries become especially complicated because we need to check if several attributes are NULL at the same time (and manage the database and the possible extension of the hierarchy to more types of requests).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> DrivingLicenseRequest (
    LicenseID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    RequestDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Fee <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Fee &gt;= <span class="hljs-number">0</span>),
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID)
);
</code></pre>
<p>Once we decide to use a table for each entity in the hierarchy, we need to reflect this decision in both the relational diagram and the SQL DDL. This is mainly because it’s <strong>not complete</strong>, <strong>disjoint</strong>, and has multiple attributes in the inheriting entities that would lead to too many <strong>NULL</strong> values.</p>
<p>So in the relational diagram, we create the corresponding tables, where <strong>DrivingLicense</strong> and RejectedDrivingLicense add foreign keys pointing to DrivingLicenseRequest to identify the request that has been rejected or accepted.</p>
<p>In other words, all requests are stored in the superclass table. Then when they are accepted or rejected, a tuple is added to the corresponding table so that its foreign key references the DrivingLicenseRequest tuple representing the request itself. This way, the superclass table is dedicated to storing requests, while the other tables focus on representing which requests have been rejected or accepted.</p>
<p>Regarding the foreign keys pointing to or present in any of the tables in the hierarchy, we can see that to know which person a certain request belongs to, there is a <strong>foreign key</strong> in DrivingLicenseRequest pointing to <strong>Person</strong>. So for every request, that foreign key indicates the person associated with that request.</p>
<p>On the other hand, given the associations we see in the conceptual diagram, there are two other foreign keys from other entities pointing to DrivingLicense. We need to consider all of this because it can affect the decision we made earlier about how to implement the hierarchy. If there are foreign keys pointing to the superclass, for example, we would necessarily have to implement a table for it.</p>
<p>Finally, we identify the requests using a surrogate key in DrivingLicenseRequest, which uniquely identifies all requests, regardless of their status. We can also see this in the inheriting entities, which don’t have any type of identification on their own, but are assumed to be identified by the primary key of DrivingLicenseRequest.</p>
<p>In other words, even though there is no clear identifier in the inheriting entities, it’s important to remember that the attributes of the superclass are inherited. So when we’re implementing the hierarchy at the logical level, no matter how we do it, we will always do it in such a way that each accepted or rejected request can be identified by the primary key of DrivingLicenseRequest**.** This is the table that stores the resolved request.</p>
<h4 id="heading-rejecteddrivinglicense-entity">RejectedDrivingLicense entity</h4>
<p>Continuing with the previous hierarchy, given its implementation, we have the table RejectedDrivingLicense, which represents its corresponding entity. Its tuples will store information regarding the rejection of requests that have been denied, such as the date or reason for rejection.</p>
<p>Also, to know which request each tuple's information corresponds to, there is a foreign key pointing to DrivingLicenseRequest, specifically referencing the tuple in that table that stores the rest of the request information (including the primary key that identifies it).</p>
<p>To avoid having to include a surrogate key in this table or define a primary key from the entity's attributes, we’ll choose the <strong>primary key</strong> to be the <strong>foreign key</strong> itself. This in turn references the primary key of the superclass table that uniquely identifies all requests, regardless of their status.</p>
<p>This means that the RejectedDrivingLicense table is weak in identification, as it requires the primary key of the owning entity DrivingLicenseRequest to identify it. But as we’ve seen before, this shouldn’t be reflected in the conceptual diagram because this way of implementing the hierarchy is not always unique. So depending on how we do it, the table may cease to be weak in identification.</p>
<p>In summary, the variability that exists when implementing an IS-A hierarchy with tables means that concepts like identification weakness aren’t indicated in the conceptual diagram, as they are only generated by certain implementations.</p>
<p>Generally, if we only look at the diagram, all we can do is consider all the options available for implementing the hierarchy, analyze each one, and even decide which one to implement in the end. But this is a decision we make and doesn’t imply what we have represented in the hierarchy of the diagram.</p>
<p>In other words, from the diagram, it’s impossible to infer which specific logical implementation has been used, although in very specific cases, it can be easier and more straightforward to "guess."</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1752916101394/f9b94685-4891-4174-b38d-35c6d164744b.png" alt="Entity-relationship diagram with incomplete and disjoint inheritance where AcceptedRequest is a subclass of Request. Image by author. " class="image--center mx-auto" width="622" height="376" loading="lazy"></p>
<p>For example, say we have a hierarchy with only one superclass <strong>Request</strong> that is pointed to by a foreign key and an inheriting entity <strong>AcceptedRequest</strong> that’s very similar to the one in our domain. We can see at the conceptual level that the hierarchy is incomplete, as there may be requests that have not yet been accepted. It’s also disjoint, which in this case makes analyzing this aspect of the hierarchy irrelevant given the number of inheriting entities it has.</p>
<p>So, since it’s incomplete, we’ll need a table for the superclass. Also, to avoid the appearance of NULL values if the hierarchy is implemented with a single table, we’ll use a table for the inheriting entity.</p>
<p>But if the hierarchy were complete, we would only have one clear way to implement the hierarchy: with a single table. This is because there would never be NULLs in the attributes of AcceptedRequest, despite the option of using a table for each entity and complicating the database logic by inserting a tuple in each table for each request.</p>
<p>With this example, we see that in very specific cases, it’s possible to infer the clearest way to implement a hierarchy at the logical level, even though there will always be some variability that prevents us from "guessing" the exact implementation chosen for the DBMS. Finally, it’s also important to consider the identification of the tuples with which we model the hierarchy, where multiple options also arise.</p>
<p>On one hand, if the domain or requirements dictate that certain entities need to have their own identifiers, then we’ll have to define them as primary keys of the corresponding entities. In our domain, all requests must be uniquely identified by an attribute in DrivingLicenseRequest, so we add a surrogate key to that entity.</p>
<p>If the requirements tell us that some of the attributes of an entity serve as an identifier, then we’ll use them as the primary key – but here for simplicity, we assume there is no domain-specific identifier, and we are the ones adding the surrogate key as an identifier to store the data in our system.</p>
<p>On the other hand, if we don't have information on how the entities should be identified, then we have the freedom to do so however we want, mainly depending on the implementation chosen in the end.</p>
<p>But regardless of the source of this identification, in general, it all comes down to whether or not each inheriting entity can be identified by its own attributes. This determines if the table it converts to at the logical level is weak in identification or not – because if we ultimately decide to define a primary key for an inheriting entity, then we will necessarily implement it with a concrete table.</p>
<p>As you can see, the identification of each entity can give us clues about how the hierarchy will be implemented, but it’s not something unequivocal that always guarantees a single way to implement it.</p>
<p>Sometimes, it’s our task to define how we identify them, and that will depend on how many tables we choose for the implementation and how we associate them with each other.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> RejectedDrivingLicense (
    LicenseID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    RejectionDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ReapplicationDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (ReapplicationDate &gt;= RejectionDate),
    Reason <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (LicenseID) <span class="hljs-keyword">REFERENCES</span> DrivingLicenseRequest(LicenseID)
);
</code></pre>
<p>In the DDL corresponding to this entity, we see that a specific table is created for it with the respective attributes shown in the conceptual diagram. Also, we include one that serves as a foreign key to reference the tuple of DrivingLicenseRequest that represents the rejected application (and also serves as the primary key of this table).</p>
<p>We could include a surrogate key here as well, but since we already have the LicenseID value from the superclass table, we don’t need to do so (and the domain doesn’t require us to identify rejected applications in a special way).</p>
<p>So we add the PRIMARY KEY and FOREIGN KEY constraints to that attribute at the same time, so it can’t contain NULL values because of the <strong>implicit NOT NULL restriction</strong> added by PRIMARY KEY. It must also reference the <strong>primary key LicenseID</strong> attribute of DrivingLicenseRequest.</p>
<p>To reflect this in the relational diagram, we can just underline the foreign key attribute, indicating that the table is weak in identification and that attribute can’t take NULL values. But to clearly indicate that other attributes that aren’t part of the key (like RejectionDate) can’t be NULL, we need to use other elements like margin notes or any other technique that clearly reflects this condition.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">ASSERTION</span> RejectionDateConstraint <span class="hljs-keyword">CHECK</span> (
    <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> RejectedDrivingLicense R
            <span class="hljs-keyword">JOIN</span> DrivingLicenseRequest D <span class="hljs-keyword">USING</span> (LicenseID)
        <span class="hljs-keyword">WHERE</span> R.RejectionDate &lt; D.RequestDate
    )
);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">ASSERTION</span> ApprovalDateConstraint <span class="hljs-keyword">CHECK</span> (
    <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> DrivingLicense D
            <span class="hljs-keyword">JOIN</span> DrivingLicenseRequest R <span class="hljs-keyword">USING</span> (LicenseID)
        <span class="hljs-keyword">WHERE</span> D.ApprovalDate &lt; R.RequestDate
    )
);
</code></pre>
<p>Finally, although we define constraints on the table – such as that the reapplication date can’t be earlier than the rejection date – there are also other constraints (like the rejection date must be after the application date).</p>
<p>These types of constraints involving information from multiple tables need to be implemented with assertions or triggers. The simplest option is to use assertions as shown above, although we haven’t yet implemented the ASSERTION statements in PostgreSQL, so attempting to define them will result in an error from the DBMS. It’ll simply ignore these definitions.</p>
<p>So we’ll choose not to implement these types of constraints at this point, assuming that the inserted data already meets them for simplicity.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">ASSERTION</span> NoSimultaneousApprovalRejection <span class="hljs-keyword">CHECK</span> (
    <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> DrivingLicense d
            <span class="hljs-keyword">JOIN</span> RejectedDrivingLicense r <span class="hljs-keyword">USING</span> (LicenseID)
    )
);
</code></pre>
<p>Also, accepted and rejected applications can’t exist at the same time, so with this assertion, we could prevent this inconsistency. Basically, we define here that there can’t be any tuple in either DrivingLicense or RejectedDrivingLicense with the same LicenseID. This means that no application (LicenseID) can appear simultaneously in both tables, as the domain requires people to submit a new application when the one they have submitted is rejected.</p>
<h4 id="heading-drivinglicense-entity">DrivingLicense entity</h4>
<p>To conclude with this hierarchy, when a driver's license application is accepted, a tuple gets created in the DrivingLicense table with which we have implemented its respective entity. Thus, the main goal of this entity is to model a person's driver's license, because once it’s accepted, it can be used to register cars, and is indirectly associated with the person who holds the license.</p>
<p>To do this, first, the DrivingLicense has a foreign key pointing to DrivingLicenseRequest, just like the previous inherited entity in the hierarchy. In turn, the request, regardless of its status, always refers to a person through its foreign key, to model whose license it is. And for cars to be registered in association with a person's driver's license, the CarRegistration entity has a foreign key pointing to DrivingLicense, so each registration necessarily refers to a specific license.</p>
<p>We can see all of this in the entity-relationship diagram through the 1-* type associations, as well as in their minimum cardinalities. But we can’t directly infer the existence of the foreign key in DrivingLicense, specific to the hierarchy implementation, because we can implement the hierarchy in many ways.</p>
<p>To understand this last point, imagine being told that there is a foreign key in DrivingLicense pointing to another entity. With this information, we can directly know that this foreign key points to the superclass of the hierarchy and exists because of the implementation where there is at least a specific table for DrivingLicense.</p>
<p>This is because the rest of the associations of the DrivingLicense entity are of the 1-* type, with the 1 on the DrivingLicense side – so these associations result in foreign keys pointing to DrivingLicense, not the other way around. In summary, with just the conceptual diagram, you can’t know exactly how a hierarchy has been implemented, but with some additional information, you can.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> DrivingLicense (
    LicenseID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    ApprovalDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (ApprovalDate &lt;= <span class="hljs-built_in">CURRENT_DATE</span>),
    Points <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (
        Points <span class="hljs-keyword">BETWEEN</span> <span class="hljs-number">0</span> <span class="hljs-keyword">AND</span> <span class="hljs-number">15</span>
    ),
    <span class="hljs-keyword">FOREIGN KEY</span> (LicenseID) <span class="hljs-keyword">REFERENCES</span> DrivingLicenseRequest(LicenseID)
);
</code></pre>
<p>The DDL of this entity is very similar to the previous one, where we have a primary key composed of the <strong>LicenseID</strong> attribute, which is also a foreign key that identifies the request that has been accepted. This refers to the tuple in the superclass table where the request is stored and uniquely identified, along with the entity's own attributes.</p>
<p>The table constraints in this case declare that the approval date must be earlier than the current date, as it’s impossible for a request to have been accepted on a date that has not yet occurred.</p>
<p>For this, we use <strong>CURRENT_DATE</strong> to get the current date in SQL and compare it with another date like the one stored in the attribute. There’s also the Points attribute, which determines the remaining points on the person's driver's license. According to the domain, this value is an integer between 0 and 15, so we restrict the possible values it can take with a CHECK, as well as with the INTEGER data type itself, preventing it from taking decimal values.</p>
<p>Given the simplicity of the attribute's domain, using a CHECK is the easiest option, although we could have defined a DOMAIN or TYPE ENUM and assigned it as the data type to the attribute. This would be useful if we had more attributes with the same domain in the rest of the schema.</p>
<h4 id="heading-bustrip-entity">BusTrip entity</h4>
<p>People in our domain can use CityBus buses as a means of transportation. To this end, we have an entity called BusTrip that models specific routes buses take across the city. Each time a bus travels from one point to another, it’s considered a trip recorded in this entity through a tuple. This tuple stores information such as the starting and ending addresses of the trip, the date it takes place, and the time it took.</p>
<p>To uniquely identify the tuples in this table, the primary key uses the attributes TripDate, the starting and ending addresses, and the foreign key attribute that identifies the specific bus that made the trip. We have to include the foreign key in the primary key because there could be several BusTrips with the same date and starting and ending addresses, all conducted by different buses.</p>
<p>So to uniquely distinguish all of them, we need to include the information of the bus making the trip, which means the value of the foreign key pointing to CityBus.</p>
<p>Regarding the semantics of this entity, we can see that no bus can make the same trip multiple times on the same date, as this would result in duplicate tuples, violating the primary key constraint. We assume that this is the case because of the characteristics of the domain.</p>
<p>In the design process, sometimes we have to model situations that may not be entirely intuitive, such as a bus not making the same trip more than once a day.</p>
<p>Since the <strong>TripDate</strong> attribute is of type <strong>DATE</strong>, it can only store dates with a resolution up to days. This means that we can’t represent the exact moment the trip occurs in our database (in the same way we could using the TIMESTAMP data type, which allows representing moments in time with date and time).</p>
<p>So, given the granularity of the DATE data type, we comply with the restriction that a bus can’t make the same trip multiple times a day (beause in that case, several tuples with exactly the same date would be stored, since DATE can only represent up to days).</p>
<p>This is an example of a restriction that is implicitly modeled by the data type of the attribute itself. If it were TIMESTAMP, we could have multiple trips by the same bus on the same day but at different times.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> BusTrip (
    TripDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    StartAddress <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    EndAddress <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Duration <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Duration &gt;= <span class="hljs-number">0</span>),
    PlateFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">PRIMARY KEY</span> (TripDate, StartAddress, EndAddress, PlateFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (PlateFK) <span class="hljs-keyword">REFERENCES</span> CityBus(Plate)
);
</code></pre>
<p>When constructing the relational diagram, we must also underline the foreign key attribute that points to <strong>CityBus</strong>, since it’s part of the primary key (it’s the weak entity in identification). More specifically, we can infer this from the entity-relationship diagram by looking at where the «weak» role is located, which indicates the <strong>owner entity</strong> of BusTrip, meaning the one it depends on for identification.</p>
<p>In the DDL, this is reflected in the attributes that make up the primary key, where we find the three from the table itself and PlateFK, which is the foreign key responsible for referencing the bus that makes the trip. We won’t impose any additional restrictions on the StartAddress and EndAddress attributes, even though just any text can’t be stored in them – only texts that represent valid addresses in a city (specifically where the bus operates).</p>
<p>For simplicity, we’ll assume that if an address is not valid, it’s the responsibility of another part of the system to check this, such as software in the application layer that validates addresses before inserting tuples into the database.</p>
<p>On the other hand, we will add the non-negativity restriction on the duration, as it doesn't make sense for it to be negative. We could name these restrictions to make database administration easier, but since we aren’t going to work on them here, we won’t do so.</p>
<h4 id="heading-busticket-entity">BusTicket entity</h4>
<p>For a person to travel on a bus route, they must have a ticket that allows them to board a bus represented in the CityBus table. So in our domain, we’ll model the existence of tickets with the BusTicket entity. Its only attribute is used to store the timestamp when it was issued.</p>
<p>It’s important to use the TIMESTAMP data type here and not DATE because a person can buy multiple tickets on the same day for different routes, which is why we need to clarify which ticket was generated first.</p>
<p>When we see how this is represented in the conceptual diagram, you might notice the XOR restriction that appears between the associations connecting BusTicket with Person and BusPass. This restriction represents that all existing tickets are either directly associated with a person who owns the ticket or are associated with a BusPass that’s owned by a person and allows multiple trips with a pass.</p>
<p>This is how we’d semantically explain the restriction we want to model – but conceptually, when we have a restriction represented by a dashed line and a logical condition like XOR, it means that either the <strong>BusTicket-Person</strong> association exists, or the <strong>BusTicket-BusPass</strong> association exists. It’s not possible for neither to exist or for both to exist at the same time.</p>
<p>Because these associations exist, the foreign key in BusTicket pointing to the respective entity is not NULL. That is, both associations are of type 1-*, so they are clearly implemented with foreign keys in BusTicket. But the minimum cardinalities on both sides are 0, indicating that the associations as a whole may not exist. In other words, it means that the values of the foreign key attributes can be NULL.</p>
<p>At this point, if we didn't have the XOR restriction, the foreign keys could both be NULL at the same time, indicating that a ticket is not associated with any person or pass, making it impossible to identify the passenger taking the trip.</p>
<p>On the other hand, if both foreign keys had values in their attributes, we would be modeling that the person has used the pass to travel by bus through the non-nullity of the <strong>BusTicket-&gt;BusPass</strong> foreign key, while at the same time modeling that the same person has not used the pass but has obtained a ticket directly through the non-nullity of <strong>BusTicket→Person</strong>.</p>
<p>That is, if the foreign key <strong>BusTicket-&gt;BusPass</strong> is not NULL, then we are modeling the situation where a person uses their pass to travel by bus, while the other foreign key, when not NULL, represents that the person is not using a pass to travel but is doing so directly with a ticket.</p>
<p>So both situations can’t occur at the same time thanks to the domain restrictions that dictate that a person either travels with a ticket or with a pass – but not both at once, and not neither. This is because a ticket is necessary to travel. This is why we use the XOR condition to represent that either one association exists or the other, but not both at the same time. It also prohibits neither from existing.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>PersonFK</strong></td><td><strong>PassFK</strong></td><td><strong>Valid</strong></td><td><strong>Meaning</strong></td></tr>
</thead>
<tbody>
<tr>
<td>No NULL</td><td>NULL</td><td>✔️</td><td>Ticket purchased directly by the person.</td></tr>
<tr>
<td>NULL</td><td>No NULL</td><td>✔️</td><td>Ticket charged to the person's BusPass.</td></tr>
<tr>
<td>NULL</td><td>NULL</td><td>❌</td><td>There is no information on which person is traveling (orphan ticket).</td></tr>
<tr>
<td>No NULL</td><td>No NULL</td><td>❌</td><td>Indicates both direct purchase and use of a pass at the same time (inconsistent).</td></tr>
</tbody>
</table>
</div><p>It’s also important to emphasize that for the foreign keys to be NULL, the minimum cardinality on the side of Person and BusPass in the associations must be 0.</p>
<p>To model that a person travels using a pass, we might consider associating the BusPass entity directly with BusTrip instead of with BusTicket. But doing this would result in an N-M relationship between BusPass and BusTrip, since a pass can lead to an indefinite number of trips, while multiple people can travel using their pass on a single trip.</p>
<p>To avoid having to add another intermediate entity to implement the N-M association, let’s associate BusTicket with BusPass, so that we can see each trip made using a pass by checking the foreign key values of the ticket.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> BusTicket (
    IssueTime <span class="hljs-type">TIMESTAMP</span>,
    TripDateFK <span class="hljs-type">DATE</span>,
    StartAddressFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    EndAddressFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    PlateFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    PersonFK <span class="hljs-type">INT</span>,
    PassFK <span class="hljs-type">INT</span>,
    <span class="hljs-keyword">PRIMARY KEY</span>(
        IssueTime,
        TripDateFK,
        StartAddressFK,
        EndAddressFK,
        PlateFK
    ),
    <span class="hljs-keyword">FOREIGN KEY</span> (
        TripDateFK,
        StartAddressFK,
        EndAddressFK,
        PlateFK
    ) <span class="hljs-keyword">REFERENCES</span> BusTrip(TripDate, StartAddress, EndAddress, PlateFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID),
    <span class="hljs-keyword">FOREIGN KEY</span> (PassFK) <span class="hljs-keyword">REFERENCES</span> BusPass(PassID),
    <span class="hljs-keyword">CONSTRAINT</span> XORConstraint <span class="hljs-keyword">CHECK</span> (
        (
            PersonFK <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
            <span class="hljs-keyword">AND</span> PassFK <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>
        )
        <span class="hljs-keyword">OR</span> (
            PersonFK <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>
            <span class="hljs-keyword">AND</span> PassFK <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
        )
    )
);
</code></pre>
<p>To uniquely identify each ticket, we have to use both the IssueTime attribute of the table and the foreign key pointing to BusTrip, which determines which trip will be made with that ticket. So we have a weak entity in identification again – and it’s peculiar in that the foreign key in this case is composed of several attributes, since the primary key of BusTrip (which is the owning entity on which it depends for identification) is itself composed of multiple attributes. Specifically, this primary key has 4 attributes – so in BusTicket, as the foreign key must reference the primary key of BusTrip, it will be composed of exactly 4 attributes (meaning as many as the primary key it points to).</p>
<p>To declare this foreign key, we use the same FOREIGN KEY constraint as always, the only difference being that here we use several attributes instead of just one.</p>
<p>The most important thing about this constraint when we have multiple attributes is to declare them in order. For example, if we want <strong>TripDateFK</strong> to point to the TripDate attribute of the BusTrip primary key, then we must put those two attributes in the same order in the constraint tuple. Here, for example, they are in the first position, but we could place them both in the second position after <strong>StartAddressFK</strong> and <strong>StartAddress</strong>, or in the third (and so on), as long as they correspond.</p>
<p>Since this is the only foreign key that can’t be NULL in the table, we need to ensure that all its attributes have the NOT NULL constraint. But since they’re part of the primary key, we don’t need to explicitly declare the constraint.</p>
<p>On the other hand, for the other foreign keys that model associations with Person and BusPass, we shouldn’t add this constraint because these foreign keys will need to take a NULL value in certain situations. So none of the attributes require us to declare constraints.</p>
<p>Finally, the TIMESTAMP data type isn’t the only one that can store date and time in the IssueTime attribute – we also have alternatives like DATETIME or TIMESTAMP WITH TIME ZONE. These have specific uses, such as storing the time zone in addition to the time itself. For simplicity, in this example, we’ll use TIMESTAMP for all attributes that need to store date and time.</p>
<h4 id="heading-buspass-entity">BusPass entity</h4>
<p>We can already infer the semantics of this entity from what we’ve just seen. Specifically, if a person plans to take multiple bus trips and doesn’t want to buy individual tickets for each of those trips, they can purchase a pass (represented by the BusPass entity) which allows them to take multiple trips without worrying about tickets.</p>
<p>If we look at the conceptual diagram, we’ll see that it has several associations of type 1-*, where one of them is affected by the XOR constraint. So given the minimum cardinalities of this association, it may not exist, as we explained earlier. So we know that there won't always be a foreign key pointing to BusPass, since the association is optional due to its minimum cardinalities.</p>
<p>But on the other hand, we have the other association with Person that results in a foreign key in BusPass that always has to exist, because all passes must have an associated person (meaning every pass must have an owner).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> ModalityType <span class="hljs-keyword">AS ENUM</span>( <span class="hljs-string">'single'</span>, <span class="hljs-string">'round_trip'</span>, <span class="hljs-string">'daily'</span>, <span class="hljs-string">'weekly'</span>, <span class="hljs-string">'monthly'</span>, <span class="hljs-string">'annual'</span> ); 
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> BusPass (
    PassID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    IssueDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ExpirationDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (ExpirationDate &gt; IssueDate),
    Modality ModalityType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    RemainingTrips <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (RemainingTrips &gt;= <span class="hljs-number">0</span>),
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID)
);
</code></pre>
<p>For the identification of this entity, we include a surrogate key to simplify the process. We could have selected another set of attributes as the primary key, although this would result in the entity being weak in identification, as well as a primary key with more attributes than it has using a surrogate key. So the simpler solution is generally preferred.</p>
<p>We should include a CHECK to ensure that the expiration date of the pass is after the issue date to prevent inserting tuples with inconsistent dates. Also, none of the attributes can be NULL. The foreign key also can’t be NULL because of the minimum cardinality that prevents it from being NULL. And finally, other attributes like modality can’t be NULL either. For these, we implement a custom ENUM TYPE where we define the different pass modalities that determine how a person can use that pass.</p>
<p>Lastly, we can indicate the constraint that we modeled at the conceptual level with an XOR in the same way in the relational diagram using a dashed line between the foreign keys involved. We can also indicate it with a textual note. But in the DDL, the simplest way to code it is with a CHECK in BusTicket, which is where the foreign keys involved in the integrity condition originate.</p>
<h4 id="heading-voyage-entity">Voyage entity</h4>
<p>Continuing with the ways people in our domain travel by cruise, we have the entity Voyage. This models the trips taken by the cruises. Specifically, the entity stores information about the trip, such as the departure and arrival dates, as well as the ports where the trip begins and ends.</p>
<p>We can also see that it has an attribute called Distance, which might initially seem irrelevant – but Distance records the total distance traveled by the cruise during the trip. And this doesn’t necessarily have to match the shortest distance between the departure and arrival ports.</p>
<p>The decision to use this meaning for this attribute came from our domain and its constraints. That is, if we are required to record the total distance the cruise travels, in addition to the distance between both ports, the simplest option would be to add an attribute in this entity that records that magnitude.</p>
<p>In other words, if we didn't need to know the distance traveled by the cruise itself, we could be satisfied with knowing the distance between the departure and arrival ports (which we can determine from the port information). But we’ll use the attribute <strong>Distance</strong> here, which records the actual distance traveled by the cruise during the trip (since we need this information).</p>
<p>If we look at the conceptual model, we’ll see that this entity has two identical associations of the same type 1-* with the entity Port, all with the aim of conceptually modeling that a voyage is associated with two ports, one for departure and one for arrival, where both can be the same. Regarding this last point, if they could not be the same, we would need to indicate that restriction with a note, as there are no standard elements in an entity-relationship diagram or in the relational model to represent such a situation.</p>
<p>On the other hand, we could also consider modeling the trip so that is has departure and arrival ports through a single Voyage-Port association with a cardinality of 2 on the Port side. But if we did this, conceptually, we wouldn't distinguish which port was for departure and which was for arrival. Rather, we would be modeling that the cruise passes through two ports on that trip – but we wouldn't know for sure which was the arrival or departure port (at least at the conceptual level) since at the logical level there would necessarily have to be two foreign keys pointing to Port.</p>
<p>So to easily distinguish between the arrival and departure ports for a trip and to clarify the semantics of the association between Voyage and Port, we’ll use multiple associations, each with a role that explicitly indicates the relationship the port has with the trip.</p>
<p>In addition to these associations, the Voyage entity needs to reference CruiseShip to know which cruise has made that trip. That's why, in the conceptual diagram, there is a 1-* association with CruiseShip, where one cruise ship can make many trips, but a trip is only made by one cruise ship.</p>
<p>To identify this entity, we’ll take advantage of the fact that both the start and end dates of the trip are always defined to include them in the primary key. This means both dates can’t be NULL as they define the trip's duration.</p>
<p>But, to truly uniquely identify the Voyage tuples, we have to distinguish them using the departure and arrival ports of the trip, as well as the cruise ship that performs it. That's why we include all foreign keys in the primary key. If we didn’t do this, there could be several tuples of different trips made by different cruise ships or passing through different ports that could still have the same value in the departure and arrival dates. So we need to include information about the cruise ship making the trip, as well as the ports involved.</p>
<p>By defining the primary key this way, we are making the entity weak in identification, where its owning entities are CruiseShip and Port, even though part of its primary key is composed of attributes from the entity itself.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Voyage (
    DepartureDate <span class="hljs-type">DATE</span>,
    ArrivalDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">CHECK</span> (ArrivalDate &gt;= DepartureDate),
    Distance <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Distance &gt;= <span class="hljs-number">0</span>),
    DepartureNameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    DepartureCityFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ArrivalNameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ArrivalCityFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ShipFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">PRIMARY KEY</span> (
        DepartureDate,
        ArrivalDate,
        DepartureNameFK,
        DepartureCityFK,
        ArrivalNameFK,
        ArrivalCityFK,
        ShipFK
    ),
    <span class="hljs-keyword">FOREIGN KEY</span> (ShipFK) <span class="hljs-keyword">REFERENCES</span> CruiseShip(ShipID),
    <span class="hljs-keyword">FOREIGN KEY</span> (DepartureNameFK, DepartureCityFK) <span class="hljs-keyword">REFERENCES</span> Port(<span class="hljs-type">Name</span>, CityFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (ArrivalNameFK, ArrivalCityFK) <span class="hljs-keyword">REFERENCES</span> Port(<span class="hljs-type">Name</span>, CityFK)
);
</code></pre>
<p>To implement this entity at the logical level, in its DDL, you can see that we first define the attributes of the entity itself, as well as those of the foreign key for the departure port, which are <strong>(DepartureNameFK, DepartureCityFK)</strong>.</p>
<p>Note that the foreign keys pointing to Port must have two attributes since the primary key of Port has two attributes. So we’ll need a total of 4 attributes to model the foreign keys that reference the departure and arrival ports of the trip, both referencing the Name and CityFK attributes of the Port table (which make up its primary key as we saw earlier). Also, we need another attribute, ShipFK, to reference CruiseShip and thus determine which cruise ship made the trip.</p>
<p>With all this, the primary key of <strong>Voyage</strong> is defined as the set of attributes <strong>(DepartureDate, ArrivalDate, DepartureNameFK, DepartureCityFK, ArrivalNameFK, ArrivalCityFK, ShipFK)</strong>.</p>
<p>If we had to infer the attributes that make up the primary key using only the conceptual diagram, we would need to look at the entities that the foreign keys reference. These are represented with the 1-* associations.</p>
<p>For example, in CruiseShip, we would see that its primary key has only one attribute, so necessarily in Voyage, the corresponding primary key that references it must have one attribute, ShipFK. Meanwhile, the other two foreign keys that reference Port need to have two attributes each, since we can see that Port is identified by its name and the city where it’s located. So its primary key has two attributes <strong>(Name, CityFK)</strong> that we will need to reference from <strong>Voyage</strong>.</p>
<p>In the relational diagram, this is easier to interpret. We’ll see that one attribute references an attribute of the CruiseShip table, so we know it’s a foreign key that leads to a 1-* association in the conceptual model.</p>
<p>Also, there are two other attributes that together reference two attributes of Port – and together, they also form a foreign key that creates a 1-* association in the conceptual diagram, where the many side is in the entity from which the foreign key originates ( that is, in Voyage).</p>
<p>With this last foreign key, we can represent the departure port of the trip. There’s another pair of attributes <strong>(ArrivalNameFK, ArrivalCityFK)</strong> that follow the same pattern to represent the arrival port of the trip. From them, we can also infer that at the conceptual level, there’s another association with the same characteristics.</p>
<p>And, since all these foreign keys are underlined, this implies they are part of the primary key of Voyage. From that we can infer that Voyage is weak in identification.</p>
<p>Lastly, if we look at the data types of the foreign keys, we’ll see that they match exactly with the types of the attributes they reference. This is especially important because a foreign key, by definition, is an attribute that holds the value of another attribute it references, so both must be of the same type for this to be possible.</p>
<p>Since foreign keys are made up of multiple attributes, in this case, we also need to consider the relative order of the attributes that form the foreign key with the order of the attributes they reference. This is unlike what happens in the PRIMARY KEY constraint, where the order in which the primary key attributes are declared doesn’t matter. In that case, in PRIMARY KEY, we are declaring a set of attributes, where what matters is that they appear in the constraint (not that they follow a specific order).</p>
<h4 id="heading-cruisebooking-entity">CruiseBooking entity</h4>
<p>For a person to travel on a cruise, they must make a reservation for a specific voyage. So in our domain, we have the entity CruiseBooking, which is responsible for storing the reservations people make to travel on a cruise.</p>
<p>The data stored for each reservation includes the booking date, cabin number, price, and payment method. To know which person has booked which voyage, the entity has 1-* associations with Person and Voyage, which logically translate into two foreign keys pointing to the respective entities.</p>
<p>To uniquely identify each booking, we could choose the easy option of including a surrogate key attribute to serve as the primary key. But to illustrate the complexity of not doing this, we’ll use only attributes from the table itself to identify its tuples. So the primary key of this entity is composed of the attributes BookingDate, CabinNumber, the foreign key to Person, and the other foreign key to Voyage.</p>
<p>We do this because we assume that multiple people can book the same cabin for the same voyage, all on the same date. For example, this can happen if several people from the same family decide to book a certain voyage. Each of those people will have a record or tuple in the CruiseBooking table with the same attributes in BookingDate, CabinNumber, and the foreign key of Voyage, but a different value in the foreign key of Person. This allows the tuples to be uniquely distinguished.</p>
<p>The foreign key to Person has a single attribute since the primary key of Person has only one attribute. But the other foreign key that refers to the voyage being booked has exactly 7 attributes (as the Voyage entity requires 7 attributes to be uniquely identified).</p>
<p>With this, we realize that the primary key of CruiseBooking will have a total of 10 attributes, making it a much more complex solution than simply using a surrogate key. So you can see why it’s very convenient to use surrogate keys whenever possible for this type of entity – especially when the foreign keys that will be part of the primary key have too many attributes, as in this case.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> PaymentMethodType <span class="hljs-keyword">AS ENUM</span> (<span class="hljs-string">'card'</span>, <span class="hljs-string">'paypal'</span>, <span class="hljs-string">'bank'</span>, <span class="hljs-string">'cash'</span>, <span class="hljs-string">'mobile'</span>);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> CruiseBooking (
    BookingDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    CabinNumber <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (CabinNumber &gt; <span class="hljs-number">0</span>),
    Price <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Price &gt;= <span class="hljs-number">0</span>),
    PaymentMethod PaymentMethodType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    DepartureDateFK <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ArrivalDateFK <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    DepartureNameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    DepartureCityFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ArrivalNameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ArrivalCityFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ShipFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">PRIMARY KEY</span> (
        BookingDate,
        CabinNumber,
        PersonFK,
        DepartureDateFK,
        ArrivalDateFK,
        DepartureNameFK,
        DepartureCityFK,
        ArrivalNameFK,
        ArrivalCityFK,
        ShipFK
    ),
    <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID),
    <span class="hljs-keyword">FOREIGN KEY</span> (
        DepartureDateFK,
        ArrivalDateFK,
        DepartureNameFK,
        DepartureCityFK,
        ArrivalNameFK,
        ArrivalCityFK,
        ShipFK
    ) <span class="hljs-keyword">REFERENCES</span> Voyage(
        DepartureDate,
        ArrivalDate,
        DepartureNameFK,
        DepartureCityFK,
        ArrivalNameFK,
        ArrivalCityFK,
        ShipFK
    )
);
</code></pre>
<p>If we look at the DDL, it seems much more complex than the previous ones. But actually, the elements we used are the same. We define the primary key with PRIMARY KEY, and the attributes of the foreign keys with the same data types as the attributes they reference. We also use the NOT NULL constraint to correctly implement what's indicated in the minimum cardinalities of the associations.</p>
<p>We declare each foreign key with FOREIGN KEY, which is longer in this case due to the number of attributes that make up each one. The only important thing to keep in mind here is that one of the FOREIGN KEYs is exclusively dedicated to declaring the foreign key to Person (meaning the association between CruiseBooking and Person) while the other models the association with Voyage.</p>
<p>We do this without mixing attributes of both foreign keys in the same FOREIGN KEY – as this would be an error since we wouldn't be modeling the conceptual diagram correctly. Each foreign key is independent of the others, so each FOREIGN KEY includes only the attributes that make up each corresponding foreign key.</p>
<p>To simplify the domain of the PaymentMethod attribute, we can define a TYPE ENUM, since the payment method is an attribute that will likely be used in other parts of the domain. Even if it's not needed now, it's possible that in a future expansion of the domain, we might need to include it in the schema. This is why it's important to declare it to make database management easier in a potential expansion.</p>
<h4 id="heading-pool-entity">Pool entity</h4>
<p>In our domain, there are also pools, which are represented in the IS-A hierarchy with the entity Pool as the superclass. This allows people to interact with pools in different ways, as we will see below. So we consider that our domain includes different types of pools, such as cruise pools found on cruise ships modeled with CruiseShip, city pools found in cities, or Olympic pools also found in cities.</p>
<p>Since they all share common attributes, we do the same as in the Vehicle hierarchy, using a superclass that includes these common attributes like the pool's name, its address, minimum and maximum depths, or the current state of the pool.</p>
<p>We also include a <strong>1-*</strong> association between <strong>Pool</strong> and <strong>City</strong> to represent that all pools are located in a city – except for those of type <strong>CruiseShip</strong>, which are on a cruise ship and not in a city. In that specific case, the semantics of the association are different, as we’ll see later. From this, we can define different types of pools with distinct characteristics, where all of them inherit all the attributes of their superclass, including the association with <strong>City</strong>.</p>
<p>As we can see, <strong>CityPool</strong> and <strong>OlympicPool</strong> have no issue with this, but <strong>CruisePool</strong> models pools on cruise ships, so its association with City does not have the same semantics as the others. In other words, the pool is not located in a city but on a cruise ship – so we assume that the associated city is its place of manufacture.</p>
<p>As you can guess, this is not the only way to model this domain, nor is it the best, since the "locatedAt" semantics indicated in the conceptual diagram's association between <strong>City</strong> and <strong>Pool</strong> does not capture the meaning of that relationship when the pool is of type CruisePool. But once we clarify this, the model is correct in the sense that all essential elements are represented correctly, even if not in the best possible way.</p>
<h4 id="heading-how-can-we-translate-the-pool-hierarchy-entities-at-the-conceptual-level-to-tables">How can we translate the pool hierarchy entities at the conceptual level to tables?</h4>
<p>Once we’ve clarified the semantics of the hierarchy, we can follow the same process as before to implement it at the logical level.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1754731726248/2494ed94-aca0-401d-abe5-1e91481f336a.png" alt="Part of the entity-relationship diagram where the IS-A hierarchy of pools is represented according to their type. Image by author." class="image--center mx-auto" width="650" height="317" loading="lazy"></p>
<p>First, we note that the hierarchy is not complete, as we assume that in our domain there are many types of pools, of which we only model 3 with specific entities, while the rest are pools modeled with occurrences of the Pool entity.</p>
<p>In other words, if a pool is one of the types of the <strong>inheriting entities</strong>, it will be represented as an occurrence of that entity, while if it’s of a different type, it will be represented by an <strong>occurrence of the superclass</strong>. So, in the hierarchy, pools aren’t required to belong to the inheriting entities, making it <strong>incomplete</strong>.</p>
<p>On the other hand, the types of pools are all disjoint, meaning a pool can’t be both Olympic and cruise at the same time, or city and Olympic at the same time. So the hierarchy is disjoint because there won’t be any pool that is of multiple types at once.</p>
<p>Just like in the DrivingLicenseRequest hierarchy, pools here are also uniquely identified with a surrogate key in the PoolID attribute, while the rest of the entities in the hierarchy initially do not have any type of identification.</p>
<p>This might lead us to think that the best way to implement the hierarchy is, once again, with a table for each entity. But this doesn't necessarily have to be the case because a single table can be used to implement multiple entities at once, using the table's identifier to distinguish between the entities. This is because we assume that the domain does not impose any restrictions, unlike in the Vehicle hierarchy where each type of vehicle had to have its own identifier.</p>
<p>Regarding the decision to implement a table for the <strong>superclass</strong>, whenever we have an <strong>incomplete hierarchy</strong>, we’ll need a specific table for the superclass – specifically to store information about pools that don’t belong to any type present in the inheriting entities. This means we need to include a <strong>Pool table</strong>.</p>
<p>Later, to decide whether to use that table to implement all entities in the hierarchy, only some of them, or to include a table for each inheriting entity, we need to look at the number of attributes the inheriting entities have. In this case, we see they have too many attributes, especially CruisePool and CityPool, so the simplest option is to implement a table for each entity in the hierarchy.</p>
<p>Another option we would have is to use the Pool table to also represent OlympicPool (which has the fewest attributes) and model the rest of the entities with specific tables. But this has disadvantages, such as the division in how we represent each type of pool.</p>
<p>For example, while we represent OlympicPool with some attributes in Pool that may or may not be NULL depending on whether the pool is of that type, the other types of pools would be represented differently. This can be confusing when querying the database.</p>
<p>We also need to consider that some foreign keys point to OlympicPool, so those foreign keys would only be valid for tuples in Pool whose corresponding attributes <strong>SpectatorMaxCapacity</strong> and <strong>CompetitionLanes</strong> aren’t NULL, greatly complicating database management, creating more constraints, and possibly complicating certain queries.</p>
<p>Although, no matter how complicated this option is, it would be possible to implement it, and it would be just as valid as implementing a table for each entity. That is, the complexity of an implementation can make it unfeasible but not incorrect – as long as the corresponding constraints are defined to maintain data integrity.</p>
<p>So even though in this case the simplest option is to use a table per entity, that doesn't mean there aren't other correct ways to implement the hierarchy. This means that from the entity-relationship diagram, we can’t infer the exact way it’s finally implemented, although it can be useful for making that decision.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> PoolStatusType <span class="hljs-keyword">AS ENUM</span> (<span class="hljs-string">'open'</span>, <span class="hljs-string">'closed'</span>, <span class="hljs-string">'maintenance'</span>, <span class="hljs-string">'renovation'</span>);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Pool (
    PoolID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Address <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    MinDepth <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (MinDepth &gt;= <span class="hljs-number">0</span>),
    MaxDepth <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (MaxDepth &gt;= MinDepth),
    Status PoolStatusType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    CityFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (CityFK) <span class="hljs-keyword">REFERENCES</span> City(CityID)
);
</code></pre>
<p>After deciding how to translate the hierarchy to the logical level, we add the table to the relational diagram and code it in the SQL DDL. As you can see, it’s very similar to the Vehicle table, with a surrogate key as an identifier, the entity attributes that characterize all pools, and a foreign key that references the City table. This determines the city where the pool is located (or manufactured in the case of a pool of the type CruisePool).</p>
<p>Regarding the status of the pool, we can see that it’s modeled here with a <strong>Status</strong> attribute. We define an ENUM TYPE for it to limit its domain. This design decision is justified because in this hierarchy we’re representing the types of pools in the inheriting entities, not their statuses. So to represent the statuses of the pools, we’ll need to use a different mechanism than <strong>generalization/specialization</strong>, such as a simple <strong>Status attribute</strong>.</p>
<p>There are other ways to model this, but they’d be more complex. This doesn’t make them wrong, but we won’t discuss or show them here.</p>
<p>To represent this attribute's data type in the entity-relationship diagram, we have chosen to define a <strong>«Enum»</strong> entity in UML with the possible values the attribute can take. Entities with the <strong>«Enum»</strong> type serve the same purpose as using a TYPE ENUM in SQL. This defines a set of values that can then be used as a data type for an attribute, thus restricting its domain.</p>
<p>But in general, this doesn’t have to be fully specified at the conceptual level. We could’ve simply used <strong>string</strong> as the data type and omitted this <strong>«Enum»</strong> entity, limiting its domain later at the logical level. Or rather, when the logical model is implemented in the DBMS.</p>
<p>Still, if we want our design to be as clear and self-descriptive as possible at all levels, we should indicate the possible values that attributes can take at all levels, as restricting the domain implicitly imposes an integrity constraint. We can do this through «Enum» entities, side notes, or by using other applicable standard UML elements.</p>
<h4 id="heading-cruisepool-entity">CruisePool entity</h4>
<p>Just as we did in the Vehicle hierarchy, here each type of pool is represented with a dedicated table. This way, when registering a new CruisePool type pool in our system, a tuple will be created in this table where the data characterizing cruise pools is stored. But the data that characterizes it as a pool won’t be stored there, as those can only be stored in the Pool table.</p>
<p>So to logically model the inheritance of all Pool attributes to the specific type of pool, we’ll use a foreign key to point to the Pool tuple that contains the rest of the pool information. Specifically, we’ll choose PoolID as the foreign key, as it’s the identifier of the pools in our system. We declare it it as the same SERIAL type to reference that same attribute in the Pool table, where it’s the primary key.</p>
<p>As you can guess, the Pool table not only stores information about pools that aren’t specifically modeled in our system, but it also contains information about pools of each of these types. So, if we want to get information about all the pools in our system, regardless of their type, we just need to query the Pool table.</p>
<p>This is possible because we have a table for the superclass, whereas in other hierarchies we might not implement it, which would require us to query multiple tables to get information about all the pools in the system. This is not necessarily a problem, but it’s worth considering when implementing the hierarchy or even modeling certain aspects of our domain with hierarchies.</p>
<p>For example, if we have a Pool and want to know its type, we must check the rest of the tables in the hierarchy to see if there is any tuple referencing that pool. This results in a very computationally expensive operation because it has to go through all the stored data. If our system needs to prioritize efficiency in such a query, it’d be helpful to modify the hierarchy implementation to make sure that this query runs as quickly as possible.</p>
<p>For instance, adding a redundant attribute in Pool to indicate the type, even though it introduces redundancy and unnecessary additional space, can greatly optimize the latency of certain queries. Just make sure you make these decisions according to project requirements, such as the latency that queries must have, the space the database should occupy, and so on.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> CruisePool (
    PoolID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    DeckNumber <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (DeckNumber &gt;= <span class="hljs-number">0</span>),
    MaxCapacity <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (MaxCapacity &gt;= <span class="hljs-number">0</span>),
    WaterTemperature <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    SlideCount <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (SlideCount &gt;= <span class="hljs-number">0</span>),
    ShipFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (PoolID) <span class="hljs-keyword">REFERENCES</span> Pool(PoolID),
    <span class="hljs-keyword">FOREIGN KEY</span> (ShipFK) <span class="hljs-keyword">REFERENCES</span> CruiseShip(ShipID)
);
</code></pre>
<p>In addition to the foreign key pointing to Pool (which also serves as the primary key, making this table weak in identification with Pool as its owner entity), we have another foreign key referencing CruiseShip to determine the cruise on which the pool is located. And, since all cruise pools must be on a cruise ship to be of that type, the foreign key pointing to CruiseShip can’t be NULL. It must always reference a valid cruise. This is why we include the NOT NULL constraint, which we don’t do for PoolID because we are declaring it as the primary key.</p>
<h4 id="heading-citypool-entity">CityPool entity</h4>
<p>Another type of pool we can find is a municipal pool, represented by the entity CityPool and implemented with its specific table. Its DDL is very similar to the previous one, with the unique feature that in this case, we have a foreign key pointing to CityPool, which can be directly inferred from the 1-* type association connecting CityPool with Entry in the conceptual diagram.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> CityPool (
    PoolID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    MaxCapacity <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (MaxCapacity &gt;= <span class="hljs-number">0</span>),
    AnnualBudget <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (AnnualBudget &gt;= <span class="hljs-number">0</span>),
    AccessibilityFeatures <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    FreeWifi <span class="hljs-type">BOOLEAN</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (PoolID) <span class="hljs-keyword">REFERENCES</span> Pool(PoolID)
);
</code></pre>
<p>In the relational diagram, it's important that the foreign key PoolID is underlined, indicating that this attribute, despite being a foreign key, is used to uniquely identify the tuples in CityPool. This means that when referencing the primary key of PoolID, the foreign key that refers to it contains exactly the value that identifies the pool in Pool.</p>
<p>So if a query simply needs the identifier of a pool of a specific type, we don’t need to access the Pool table, as the foreign key attribute of the CityPool, CruisePool, or OlympicPool table, for example, is enough to know it.</p>
<p>There are even times when we can access data from other tables that are indirectly associated through more levels of association, as in CruiseBooking, where we can access the identifier of a CruiseShip through the value of its foreign key, which doesn't point directly to CruiseShip, but to Voyage.</p>
<h4 id="heading-olympicpool-entity">OlympicPool entity</h4>
<p>Regarding the last type of pool in our schema, there's OlympicPool, which represents Olympic pools. The implementation of this entity as a table is the same as the previous ones, with the difference that in the entity-relationship diagram, we can see that there are two foreign keys pointing to OlympicPool. Otherwise, the only differences are in the attributes that characterize the type of pool.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> OlympicPool (
    PoolID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    SpectatorMaxCapacity <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (SpectatorMaxCapacity &gt;= <span class="hljs-number">0</span>),
    CompetitionLanes <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (CompetitionLanes &gt; <span class="hljs-number">0</span>),
    <span class="hljs-keyword">FOREIGN KEY</span> (PoolID) <span class="hljs-keyword">REFERENCES</span> Pool(PoolID)
);
</code></pre>
<h4 id="heading-entry-entity">Entry entity</h4>
<p>Continuing with what a person can do in a pool in our system, we have the entity Entry. This is responsible for storing tickets that a person can use to enter a municipal pool, meaning one that is represented by the CityPool entity only.</p>
<p>To ensure that a person can only access a municipal pool with these tickets, the entity has a 1-* association with CityPool, and not directly with Pool, as that would give access to any pool regardless of type. Also, to know which person the ticket belongs to, it also has a 1-* association with Person, where a person can have an arbitrary number of tickets, but a ticket can only belong to one person.</p>
<p>On the other hand, we also have a 1-* association where the 1 side is in Entry, modeling that the tickets can have associated penalties, which we’ll see later. So, with all this, we can know that at a logical level, Entry will have 2 foreign keys pointing to other entities, as well as a foreign key from another entity pointing to Entry.</p>
<p>To uniquely identify the tickets, the most important attribute is <strong>EntryTimestamp</strong>. This records the exact time the ticket was purchased. But several people can buy tickets at the same time to enter the same pool, leading to multiple tuples with the same <strong>EntryTimestamp</strong> value, so the primary key must have more attributes to uniquely identify all the tickets.</p>
<p>Specifically, the primary key needs the foreign key attributes <strong>PersonFK</strong> and <strong>PoolFK</strong> to differentiate entries by the person who bought them and the pool they enter, as well as the exact time of purchase. So if we consider the possible situations and combinations of values that can occur for the primary key of Entry, we’ll see that a person can’t buy multiple entries at the exact same moment to enter the same pool.</p>
<p>This makes sense when the domain states that each ticket is associated with a single person and that a person can’t buy a ticket for someone else. In other words, if a person buys a ticket, they must use it themselves. They can’t buy multiple tickets for several people to enter. This doesn't have to be the case in all domains – we're just assuming here that people can't buy tickets for others.</p>
<p>In other domains, this might need to be modeled differently depending on the requirements. So, we’ll need to make sure that our model meets these types of requirements imposed by the domain, especially when defining <strong>primary keys</strong> or <strong>UNIQUE</strong> constraints.</p>
<p>So by requiring the attributes <strong>PersonFK</strong> and <strong>PoolFK</strong> to be present in the primary key, the Entry entity becomes weak in identification with two owning entities, Person and CityPool, respectively. In the DDL, we have explicitly added the NOT NULL constraint to all attributes for clarity, although it wouldn't be necessary for those present in the primary key.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Entry (
    EntryTimestamp <span class="hljs-type">TIMESTAMP</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Price <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Price &gt;= <span class="hljs-number">0</span>),
    PaymentMethod PaymentMethodType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    AppliedDiscount <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (AppliedDiscount &gt;= <span class="hljs-number">0</span>),
    Duration <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Duration &gt;= <span class="hljs-number">0</span>),
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    PoolFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">PRIMARY KEY</span> (EntryTimestamp, PersonFK, PoolFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID),
    <span class="hljs-keyword">FOREIGN KEY</span> (PoolFK) <span class="hljs-keyword">REFERENCES</span> CityPool(PoolID)
);
</code></pre>
<p>On the other hand, the <strong>EntryTimestamp</strong> attribute of type TIMESTAMP is named differently from the IssueTime attribute of the BusTicket entity, for example.</p>
<p>This isn't very important, but in a real design process, we might be required to use style guides that determine how we should name each attribute depending on its semantics, type, or constraints, as well as when and how we should declare certain constraints. In this specific case, we didn't follow any style guide – we simply named the attributes as descriptively as possible according to the circumstances. Still, following a style guide offers advantages in system maintainability and ease of administration, among others.</p>
<h4 id="heading-team-entity">Team entity</h4>
<p>To hold competitions in Olympic pools, our system needs to be able to model sports teams made up of people who participate in these competitions. So we have the entity Team, which represents sports teams that have a reference Olympic pool, are made up of people, and participate in competitions in Olympic pools.</p>
<p>This is modeled by using the attributes of Team to store the characteristics of the sports teams, such as the name, creation date, uniform color, and so on. We can also use associations with other entities to determine which Olympic pool is the team's official pool, which people belong to the team, who coaches the team, and which competitions they participate in.</p>
<p>First, to model the Olympic pool considered the team's official pool, we’ll use a 1-* association with OlympicPool, which becomes a foreign key due to its cardinality. As you can see in the conceptual diagram, the role of the association specifies the semantics, since without it, you can’t directly infer what is being modeled with that association.</p>
<p>The same applies to the 1-* association with Person, which we use to determine who coaches the team, so we need to specify its semantics to avoid confusion about what that association actually models. Although, given their cardinalities, it’s clear that a team can only have one person as a coach, not an arbitrary number of people, so we can rule out that the association models the people who belong to the team.</p>
<p>On the other hand, besides the foreign keys that Team has, there are others that point to Team and are responsible for modeling the people who make up the team, such as the one from Membership, or the team's participation in competitions, like the one we see from Participation.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> SportType <span class="hljs-keyword">AS ENUM</span> (<span class="hljs-string">'waterpolo'</span>, <span class="hljs-string">'swimming'</span>, <span class="hljs-string">'diving'</span>);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Team (
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    CreationDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ClothColor ColorType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Sport SportType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Budget <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Budget &gt;= <span class="hljs-number">0</span>),
    ContactEmail <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    CoachFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    HomePoolFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">PRIMARY KEY</span> (<span class="hljs-type">Name</span>, CoachFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (CoachFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID),
    <span class="hljs-keyword">FOREIGN KEY</span> (HomePoolFK) <span class="hljs-keyword">REFERENCES</span> OlympicPool(PoolID)
);
</code></pre>
<p>To uniquely identify each team, the attribute that can serve us best from the table itself is Name. But in this domain, we assume that multiple teams can have the same name, so the primary key can’t be formed solely by that attribute.</p>
<p>So from all the other attributes we have, we finally include the foreign key CoachFK in the primary key, meaning we also use the information of the person who coaches the team to uniquely identify it. This works because we assume that there can’t be multiple teams with the same name coached by the same person.</p>
<p>At first glance, this might seem entirely possible, but consider that some domain requirements might impose this condition, which we can leverage to define <strong>(Name, CoachFK)</strong> as the primary key. In any case, before making such a decision, make sure that the set of attributes meets the primary key restriction, either due to domain requirements or the semantics of the attributes themselves.</p>
<p>We can declare foreign keys with FOREIGN KEY referencing the primary key of Person and OlympicPool. We impose the NOT NULL restriction on them since all teams must have a coach and an official Olympic pool. Here, we have also assumed the necessity of these elements, but in other cases it might not be mandatory to have an official pool or a coach – it all depends on the domain.</p>
<p>If having a coach were not mandatory, we couldn’t include the foreign key attribute CoachFK in the primary key, as it could be NULL and would violate the primary key restriction. So for an entity to be weak in identification and another to be its owner, the association between them must be mandatory, meaning its minimum cardinality on the owner's side can’t be 0.</p>
<p>Finally, we define a TYPE ENUM here for the type of sport the team plays, which is stored in the Sport attribute. But we don’t need to redefine it for the <strong>Color</strong> attribute, as we had the <strong>ENUM ColorType</strong> defined earlier, which is the best example of how a data type is <strong>reused</strong> across attributes with the same domain in different entities.</p>
<h4 id="heading-membership-entity">Membership entity</h4>
<p>We’ll continue with the semantics of the previous entity. To model the possibility of people being part of a team, the simplest approach would be to include an N-M association between Person and Team. This would be in addition to the 1-* association that already exists to model the person who coaches the team. This way, a person can belong to an arbitrary number of teams, while a team can be composed of an arbitrary number of people.</p>
<p>But since this association requires an intermediate entity to be implemented at the logical level, and we also need to store information about a person's membership in a team, we’ll introduce the Membership entity. This entity divides the N-M association into several 1-* associations, indirectly connecting Person with Team. In this way, each person belonging to a team will have a tuple in this table representing their membership. It’ll store information such as the start or end date of membership or the fee they must contribute to the team to be part of it.</p>
<p>At the conceptual level, we can see that this entity has many similarities with others like Residence. For example, we define the primary key of this entity with the attribute JoinDate and the foreign keys that determine the Person who belongs to a certain team. This is because the attributes that appear exclusively in the entity can’t uniquely identify each membership. That is, there can be multiple people who started belonging to different teams on the same date, causing multiple tuples in Membership with the same value in their primary key.</p>
<p>So even though the foreign key attributes don’t explicitly appear at the conceptual level, it’s clear that a Membership tuple must be identified not only by the start date but also by the person and team it relates to. This will avoid situations where multiple tuples with the same person and date are considered equal, or with the same team and start date. So we know it’s a weak entity in identification that’s dependent on Person and Team.</p>
<p>Since it depends on both entities it’s related to for identification, we could have represented it as an associative entity connected with the possible N-M association between Person and Team. But to make the diagram as clear and close to the logical level as possible, we should instead use an "intermediate" entity like the one represented here with 1-* associations.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> PaymentFrequencyType <span class="hljs-keyword">AS ENUM</span>(<span class="hljs-string">'monthly'</span>, <span class="hljs-string">'anual'</span>, <span class="hljs-string">'weekly'</span>, <span class="hljs-string">'quarterly'</span>);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Membership (
    JoinDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    LeaveDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">CHECK</span> (
        LeaveDate <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
        <span class="hljs-keyword">OR</span> LeaveDate &gt;= JoinDate
    ),
    FeeAmount <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (FeeAmount &gt;= <span class="hljs-number">0</span>),
    PaymentFrequency PaymentFrequencyType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    AutoRenewal <span class="hljs-type">BOOLEAN</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    TeamNameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    CoachFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">PRIMARY KEY</span> (JoinDate, PersonFK, TeamNameFK, CoachFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (PersonFK) <span class="hljs-keyword">REFERENCES</span> Person(PersonID),
    <span class="hljs-keyword">FOREIGN KEY</span> (TeamNameFK, CoachFK) <span class="hljs-keyword">REFERENCES</span> Team(<span class="hljs-type">Name</span>, CoachFK)
);
</code></pre>
<p>To implement the foreign keys, we’ll create the corresponding attributes: PersonFK, which is the foreign key pointing to Person, and (TeamNameFK, CoachFK), where both constitute the other foreign key referencing the team to which the person belongs. Both keys are <strong>not null</strong> because a Membership tuple must associate a person with a team.</p>
<p>Once we’ve declared the attributes and FOREIGN KEY constraints, we can define the primary key as the set of attributes consisting of <strong>JoinDate</strong>, the foreign key attribute <strong>PersonFK</strong>, and the other two attributes <strong>(TeamNameFK, CoachFK)</strong> of the foreign key referencing the team. We can declare them in any order in the PRIMARY KEY constraint, as long as they all appear.</p>
<p>Finally, according to the domain, we assume that people don’t know exactly when they will stop being members of a team, so LeaveDate doesn’t always have to be defined. This means it can be NULL until the person leaves the team or plans to leave on a specific date. So we have to define a CHECK constraint on that attribute to make sure that it’s either NULL or the date is after JoinDate, as a person can’t leave a team before the start date of membership.</p>
<h4 id="heading-participation-entity">Participation entity</h4>
<p>Similarly, a sports team can also participate in sports competitions registered in SwimmingCompetition. So we have an entity called Participation that indirectly links Team with SwimmingCompetition through 1-* associations. This is just like we saw earlier with Membership, but with a different meaning. Specifically, what mainly changes is the information stored about the team's participation in a competition, such as the date they register to participate, their ranking position after the competition, or the time it took to complete the competition.</p>
<p>To uniquely identify the tuples of Participation, the simplest way is to use a custom database identifier as a surrogate key, just as we have done before with certain entities. But if the domain requirements don’t allow us to include surrogate keys or any additional database-specific identifier, we’ll need to choose a set of attributes that enable identification.</p>
<p>So if we assume that no team participates more than once in the same competition (as this wouldn't make sense), we can declare a primary key formed by the foreign keys referencing <strong>Team</strong> and <strong>SwimmingCompetition</strong>. This way, we ensure that different tuples of Participation don’t associate the same team with the same competition, as that situation can’t occur.</p>
<p>As you can see, identifying this entity completely depends on other entities like Team and SwimmingCompetition, meaning there is no attribute at the conceptual level of the entity that forms part of the primary key.</p>
<p>This isn’t necessarily a bad thing, but rather a consequence of the domain requirements preventing us from using a surrogate key. In fact, this dependency in identification can have certain advantages, such as avoiding additional columns, which might be a domain-imposed requirement (to use the fewest columns possible).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Participation (
    RegistrationDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    Rank <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Rank &gt; <span class="hljs-number">0</span>),
    RecordedTime <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (RecordedTime &gt;= <span class="hljs-number">0</span>),
    NameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    StartDateFK <span class="hljs-type">DATE</span>,
    EndDateFK <span class="hljs-type">DATE</span>,
    TeamNameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    CoachFK <span class="hljs-type">INT</span>,
    <span class="hljs-keyword">PRIMARY KEY</span> (
        NameFK,
        StartDateFK,
        EndDateFK,
        TeamNameFK,
        CoachFK
    ),
    <span class="hljs-keyword">FOREIGN KEY</span> (TeamNameFK, CoachFK) <span class="hljs-keyword">REFERENCES</span> Team(<span class="hljs-type">Name</span>, CoachFK),
    <span class="hljs-keyword">FOREIGN KEY</span> (NameFK, StartDateFK, EndDateFK) <span class="hljs-keyword">REFERENCES</span> SwimmingCompetition(<span class="hljs-type">Name</span>, StartDate, EndDate)
);
</code></pre>
<p>At the logical level, the foreign key referencing Team has two attributes, which make up the primary key of Team. The foreign key pointing to SwimmingCompetition has three for the same reason. So we’ll use two FOREIGN KEY constraints: one to declare the foreign key pointing to Team and the other for the one pointing to SwimmingCompetition, respectively.</p>
<p>Note that the FOREIGN KEY constraint only allows one REFERENCES clause. So if we have multiple foreign keys pointing to various entities, we have to use a separate FOREIGN KEY constraint for each foreign key. If we try to declare them all with a single constraint, we would have to indicate the multiple entities/tables being referenced, which means we would need to use multiple REFERENCES statements.</p>
<p>After declaring the foreign keys and adding their respective NOT NULL constraint, since it’s mandatory for a participation to relate a team with a competition, we declare the foreign key as the set of attributes that form both foreign keys together. So in our system, there can be Participation tuples with different Rank or RegistrationDate values without any problem – but there can’t be multiple tuples with the same value in their primary key (meaning they can’t relate the same team with the same competition multiple times).</p>
<p>Finally, if we try to reconstruct the conceptual entity from the relational diagram, the first thing we should notice is that all the foreign keys are underlined, and therefore form the primary key. As they are foreign keys, these attributes won’t appear in the conceptual entity of Participation.</p>
<p>To determine how many foreign keys we actually have, and know how many 1-* associations to introduce and with which entities to connect them, we can see that a subset of attributes like <strong>(TeamNameFK, CoachFK)</strong> refers to the same entity – so there will be a 1-* relationship with that entity, with the many side in Participation. Doing the same with the attributes <strong>(NameFK, StartDateFK, EndDateFK)</strong>, we see that they all refer to attributes of the same entity. So they form a foreign key that results in a 1-* association like the previous one, but connecting with another entity.</p>
<p>To infer the minimum cardinalities, we should look at the constraints indicated in the relational diagram: which foreign keys can or can’t be NULL, or how many participations each competition must have (as well as the participations each team must have).</p>
<p>In this case, we haven’t indicated any constraints in the relational diagram for simplicity. But, for example, if we were told that a foreign key can’t be NULL in the relational model, this conceptually translates to its respective 1-* association having a minimum cardinality of 1 on the 1 side. Similarly, if there are special constraints that require each team to have 2 participations, for example, then we know that in its corresponding association, the minimum cardinality on the Participation side would be 2.</p>
<p>This reverse process is what we initially followed to implement the entity at the logical level, where the attributes that make up each foreign key are inferred, and those selected to declare the primary key.</p>
<h4 id="heading-swimmingcompetition-entity">SwimmingCompetition entity</h4>
<p>To model the sports competitions that can take place in an Olympic pool, in the conceptual diagram we have the entity called <strong>SwimmingCompetition</strong> that’s responsible for storing information about the competitions held in all the Olympic pools registered in the system. In these, any number of sports teams can participate.</p>
<p>The information that SwimmingCompetition stores mainly depends on the domain and requirements. In this case, we assume that we only need to store the name of the competition, start and end dates that will always be determined, a RecordTime attribute to store any record times achieved during the course of that competition, and the monetary amount of the prize for that competition.</p>
<p>With these attributes, the simplest way to uniquely identify each tuple in the SwimmingCompetition table is to define the set of attributes <strong>(Name, StartDate, EndDate)</strong> as the primary key.</p>
<p>For example, there can be competitions in the database with exactly the same name, but they can never have the same start and end dates simultaneously (because that would mean they were the same competition). Ultimately, by declaring this primary key, we’re assuming that there are no different competitions with the same name and start and end dates – so if this condition aligns with the domain requirements, it would be correct.</p>
<p>Consequently, there can be different competitions in the database with different combinations of values for the primary key attributes – but they might have the <strong>same record time</strong>, or the same prize in <strong>PrizeAmount</strong>, since there are no restrictions preventing it.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> SwimmingCompetition (
    <span class="hljs-type">Name</span> <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    StartDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    EndDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (EndDate &gt;= StartDate),
    RecordTime <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">CHECK</span> (RecordTime &gt;= <span class="hljs-number">0</span>),
    PrizeAmount <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (PrizeAmount &gt;= <span class="hljs-number">0</span>),
    <span class="hljs-keyword">PRIMARY KEY</span> (<span class="hljs-type">Name</span>, StartDate, EndDate)
);
</code></pre>
<p>In the conceptual diagram, we see that the entity has several associations that lead to the existence of a foreign key pointing to OlympicPool, since the competition must necessarily take place in an Olympic pool. So this foreign key references the specific pool where the competition is held, making its existence mandatory. In other words, the foreign key can’t be NULL because, in the conceptual model, we set the minimum cardinality to 1 to ensure that every competition is associated with a pool where it takes place.</p>
<p>Another peculiarity of this entity is that the attribute <strong>RecordTime</strong> may not always be defined. For example, when we register a competition in the database and need to provide a value for this attribute, such value might not exist because it’s the first time the competition is being held. So, the simplest way to model it would be to set that attribute to the maximum or minimum possible, depending on how we consider which times are better than others.</p>
<p>Additionally, since in our domain we also model the possibility of athletes participating in a competition being sanctioned, there is a chance that in a certain competition held for the first time, all participants could be sanctioned. This means that none of them would contribute to initializing the value of the <strong>RecordTime</strong> attribute. This is why it needs to be allowed to be <strong>NULL</strong>.</p>
<p>But this is a decision we must make primarily considering the domain and its requirements, as we may want to initialize the attribute with a default or special value if all athletes are penalized and the counter can’t be initialized, for example.</p>
<h4 id="heading-sanction-entity">Sanction entity</h4>
<p>Given everything a person can do in our domain in relation to other entities, they might break a rule that results in a sanction. So in our schema, we can introduce an IS-A hierarchy where the superclass is the entity Sanction, and its inherited entities are the different types of sanctions we define, all depending on their scope of application.</p>
<p>Specifically, deciding to use a hierarchy to model sanctions is driven by the specific information that needs to be stored for each type of sanction. For this reason, if we tried to use a single Sanction entity to represent all these types, its semantics would be very complicated (as some attributes would only be useful if the sanction were of a certain type – and the same goes for many others). We would also need to use a specific attribute to represent the sanction type, since otherwise knowing the exact type might depend on which attributes were NULL, and this would complicate queries.</p>
<p>So with this hierarchy, we can have a set of common attributes for all sanctions in Sanction, such as the monetary amount of the fine, the description, the date of the sanction, or the status, while in the inherited entities, we have specific attributes that characterize each type of sanction.</p>
<h4 id="heading-how-is-the-is-a-hierarchy-implemented-with-tables">How is the IS-A hierarchy implemented with tables?</h4>
<p>Just as we have done with other hierarchies, we need to analyze it to know how to implement it at the logical level. We need to keep in mind that the conceptual design doesn’t unequivocally determine the implementation that we’ll ultimately carry out, especially when working with IS-A hierarchy. Rather, it’s a decision we should make based not only on the conceptual design itself, but also on the domain and data requirements.</p>
<p>To do this, we first check whether the hierarchy is complete or not. In this case, all existing sanctions will be of a specific type represented by the inherited entities. This means that all individuals in the hierarchy will belong to one of the sets generated by these entities, which implies that the hierarchy is <strong>complete</strong>.</p>
<p>On the other hand, the types of sanctions are all disjoint, meaning a sanction can only be of one type, not several at once. This means that the hierarchy is disjoint because no individual will be represented by multiple inherited entities at the same time.</p>
<p>To identify each sanction, we’ll use a SanctionID attribute in the superclass Sanction, which we’ll implement using a surrogate key. This avoids the inherited entities needing to use their own identifiers, as we assume that the domain requirements don’t require us to identify each type of sanction differently.</p>
<p>So given the number of attributes each inherited entity has, it’s clear that we’ll need a table to implement each inherited entity. Otherwise, too many NULL values would be generated in the corresponding attributes, complicating both database management and queries, and potentially leading to unnecessary constraints aimed at ensuring schema integrity.</p>
<p>On the other hand, we have several options for implementing the superclass at the logical level. One option is to duplicate all attributes in each of the tables of the specific sanction types.</p>
<p>This has advantages, such as identifying each table using the SanctionID attribute inherited from the superclass, but it leads to schema management problems. If we later want to delete, modify, or add an attribute of Sanction, we would have to perform that operation on all the tables of the different sanction types, increasing the likelihood of errors in the process. Also, if we want to query all the sanctions in our database, with this option, we would have to go through all the tuples of all the tables of each sanction type, which could be inefficient because of accessing multiple tables.</p>
<p>To minimize errors in the database management process, we need to simplify the operations involved as much as possible. To do this, we can implement a specific table for the superclass of the hierarchy in the same way as we did with the Vehicle hierarchy (and for similar reasons).</p>
<p>Each of the tables for the inherited entities will have a foreign key referencing the superclass table, where we’ll store the information of attributes common to all sanctions. This makes it easier to modify these attributes. It also simplifies other operations, such as adding a new type of sanction. For this, only a new table for that type needs to be created, and we just need to make sure that its foreign key references <strong>Sanction</strong>.</p>
<p>If we look at the inherited entities, we’ll see that each one has a 1-* association with other entities where the many side is always in the entities of the hierarchy. This means that using a single table to implement the entire hierarchy isn’t a good idea, as it would combine all those foreign keys into one table. This would lead to much more complicated integrity constraints.</p>
<p>In other words, if a sanction is of a specific type, the attributes and foreign keys of the remaining types must be NULL, so ensuring this for all types involves overly elaborate and complex constraints.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TYPE</span> SanctionStatusType <span class="hljs-keyword">AS ENUM</span> (<span class="hljs-string">'created'</span>, <span class="hljs-string">'active'</span>, <span class="hljs-string">'expired'</span>);
<span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> Sanction (
    SanctionID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    Amount <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (Amount &gt;= <span class="hljs-number">0</span>),
    Description <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>),
    IssueDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    ExpirationDate <span class="hljs-type">DATE</span> <span class="hljs-keyword">CHECK</span> (
        ExpirationDate <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
        <span class="hljs-keyword">OR</span> ExpirationDate &gt;= IssueDate
    ),
    Status SanctionStatusType <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>
);
</code></pre>
<p>In the DDL of the Sanction table, we can see that its primary key <strong>{SanctionID}</strong> consists of a single attribute of type SERIAL. This is a surrogate key that will be used to identify all sanctions in the database, regardless of their type.</p>
<p>This table also stores the status of the sanction in an attribute, since the type of sanction is represented with inherited entities from the superclass at the conceptual level. So the status must be modeled as an attribute to avoid mixing the semantics of what we represent with each tool of the entity-relationship diagram.</p>
<p>In other words, we could include new inherited entities that model the states of the sanctions, but we have to consider that each type of sanction could be in any of those states – leading to an unnecessarily complicated multi-level hierarchy.</p>
<p>Because of this, we should separate the semantics of what we represent with inherited entities from the semantics of the sanction's status, modeling it with an attribute in the superclass, as any type of sanction can be in any state.</p>
<p>In this Status attribute, we define a TYPE ENUM to restrict the possible states a sanction can have. But for the Description, if we want to save a description of the sanction written in natural language, we shouldn’t add restrictions unless it’s required by the project specifications.</p>
<p>A description in natural language can be very diverse, so the simplest approach is not to limit the possible values the attribute can take, not even with a NOT NULL constraint. This can indicate that a sanction has no description, although this isn’t necessarily correct.</p>
<p>In general, decisions to allow NULL values also depend on the domain and requirements. For example, sanctions may or may not have an expiration date, which is why the CHECK constraint defined on ExpirationDate specifies that this attribute can either be NULL or must hold a date later than the issuance date of the sanction.</p>
<h4 id="heading-drivingsanction-entity">DrivingSanction entity</h4>
<p>Let’s now talk about the different types of sanctions in our system. First, we have DrivingSanction, which are sanctions associated with driver's licenses. So in the conceptual diagram, it has a 1-* association with the DrivingLicense entity, resulting in a foreign key in DrivingSanction that references the driver's license with the sanction. This refers to the license of the person who committed a traffic violation, leading to the existence of the fine.</p>
<p>The specific attributes of this type of sanction are store information about why the fine was issued, such as the speed the vehicle was going, as well as the effect the sanction has on the license (like deducting a certain number of points or suspending it for a certain period).</p>
<p>In its DDL, we can see that all attributes have been declared as NOT NULL, which at first might seem unnecessary in the case of RecordedSpeed, since not all sanctions are caused by speed. But this illustrates that even if an attribute isn’t necessary, it shouldn’t be NULL to be considered unnecessary.</p>
<p>For example, if a sanction is not related to speed, instead of using a NULL value in the RecordedSpeed attribute, we can use a special value like 0, as long as it respects the integrity constraints and system domain requirements. This allows us to distinguish whether the sanction is related to a possible speeding violation. So we make the decision to allow NULL or not is initially when modeling the entity at the logical level. This works as long as we aren’t forced to use a specific semantics like setting the attribute to 0 when it’s not necessary.</p>
<p>If we consider whether other attributes can be NULL or not, we can see that PermanentSuspension always has the option to take the value <strong>false</strong> (as the suspension might not be permanent). Similarly, if the suspension is permanent, the SuspensionDays attribute can always be set to 0, or to a different special value. We could also simply ignore its value and check first if the suspension is permanent before accessing the SuspensionDays attribute, among other options.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> DrivingSanction (
    SanctionID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    RecordedSpeed <span class="hljs-type">DOUBLE</span> <span class="hljs-type">PRECISION</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (RecordedSpeed &gt;= <span class="hljs-number">0</span>),
    PointsDeducted <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (PointsDeducted &gt;= <span class="hljs-number">0</span>),
    SuspensionDays <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (SuspensionDays &gt;= <span class="hljs-number">0</span>),
    PermanentSuspension <span class="hljs-type">BOOLEAN</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    LicenseFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (SanctionID) <span class="hljs-keyword">REFERENCES</span> Sanction(SanctionID),
    <span class="hljs-keyword">FOREIGN KEY</span> (LicenseFK) <span class="hljs-keyword">REFERENCES</span> DrivingLicense(LicenseID)
);
</code></pre>
<p>On the other hand, the NOT NULL is indeed necessary for both foreign keys in the table, as SanctionID is the foreign key that references the tuple in Sanction that holds the rest of the sanction information. Its primary key attribute SanctionID serves as the primary key of the DrivingSanction table itself, and it’s the only way to uniquely identify the sanctions. Also, the foreign key that references the driving license that received the sanction can’t be NULL either, because if the sanction is of type DrivingSanction, it must necessarily be associated with a license.</p>
<h4 id="heading-sportsanction-entity">SportSanction entity</h4>
<p>Another type of sanction is represented in the entity SportSanction. This models those sanctions that occur in sports competitions, specifically those caused by a sports team while participating in a competition. Like the previous entity, it has attributes that characterize this type of sanction, such as the number of competitions the team is suspended or the name of the referee who issued the sanction.</p>
<p>In addition to this information, each sanction of this type needs to know which specific team received the sanction, as well as the competition they were participating in when they were sanctioned. So to model this, we have multiple options. We could use two 1-* associations to connect SportSanction with Team and with SwimmingCompetition, so that from the sanction you can identify the corresponding team and competition. But this is redundant and unnecessary, as it would lead to two foreign keys that can actually be reduced to one.</p>
<p>Remember that in our schema, we have an entity called Participation that relates teams to the competitions they participate in. So instead of two 1-* associations in SportSanction, we can use just one that connects it with Participation, since from Participation we can determine the team and competition.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> SportSanction (
    SanctionID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    SuspendedCompetitions <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (SuspendedCompetitions &gt;= <span class="hljs-number">0</span>),
    RefereeName <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    NameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    StartDateFK <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    EndDateFK <span class="hljs-type">DATE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    TeamNameFK <span class="hljs-type">VARCHAR</span>(<span class="hljs-number">32</span>) <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    CoachFK <span class="hljs-type">INT</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (SanctionID) <span class="hljs-keyword">REFERENCES</span> Sanction(SanctionID),
    <span class="hljs-keyword">FOREIGN KEY</span> (
        NameFK,
        StartDateFK,
        EndDateFK,
        TeamNameFK,
        CoachFK
    ) <span class="hljs-keyword">REFERENCES</span> Participation(
        NameFK,
        StartDateFK,
        EndDateFK,
        TeamNameFK,
        CoachFK
    )
);
</code></pre>
<p>To implement this in SQL, we can create a table very similar to DrivingSanction, where its primary key is the attribute SanctionID, also declared as a foreign key referencing the Sanction table of the superclass. We can declare attributes in the same way as we have been doing so far, both for the attributes of the entity itself and for the foreign keys. The foreign keys must have the same data types as the attributes they reference.</p>
<p>In this case, to declare the foreign key that points to Participation, we need as many attributes as its respective primary key has, which is a total of 5. To simplify this process, the ideal approach is to look directly at the PRIMARY KEY constraint of the table we want to reference. Then for each of those attributes, we can declare it in our table with a characteristic name and the corresponding data type. We finally add it to the FOREIGN KEY constraint so that it references the attribute that originated it, as we have already seen.</p>
<p>For example, if the primary key of Participation is <strong>(NameFK, StartDateFK, EndDateFK, TeamNameFK, CoachFK)</strong>, then we declare an attribute <strong>NameFK</strong> for the foreign key of <strong>SportSanction</strong> that points to the <strong>NameFK</strong> attribute of that primary key, another <strong>StartDateFK</strong> that points to the <strong>StartDateFK</strong> attribute of the primary key of <strong>Participation</strong>, and so on.</p>
<h4 id="heading-poolsanction-entity">PoolSanction entity</h4>
<p>To conclude the hierarchy of sanctions, we have PoolSanction. These, as you can guess, are sanctions imposed on people who have entered a CityPool and violated the pool rules. In this case, we store start and end dates as attributes, indicating the period during which the person can’t enter the pool. We can also include an amount as compensation if necessary, or a number of community service hours that the person must complete.</p>
<p>To determine from the sanction which person and pool are affected by the sanction, we can use a 1-* association with Entry. This results in a foreign key in PoolSanction that points to Entry because the many side is placed in PoolSanction. This way, we can identify the entry the person used when they received the sanction.</p>
<p>Besides the person, the entry also provides information about the pool they will no longer be able to enter freely. The sanction determines when they can re-enter or the action they must take due to being sanctioned.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">TABLE</span> PoolSanction (
    SanctionID <span class="hljs-type">SERIAL</span> <span class="hljs-keyword">PRIMARY KEY</span>,
    BanStartDate <span class="hljs-type">DATE</span>,
    BanEndDate <span class="hljs-type">DATE</span>,
    CompensationRequired <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (CompensationRequired &gt;= <span class="hljs-number">0</span>),
    CommunityServiceHours <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">CHECK</span> (CommunityServiceHours &gt;= <span class="hljs-number">0</span>),
    EntryFK <span class="hljs-type">TIMESTAMP</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    PersonFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    PoolFK <span class="hljs-type">INT</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span>,
    <span class="hljs-keyword">FOREIGN KEY</span> (SanctionID) <span class="hljs-keyword">REFERENCES</span> Sanction(SanctionID),
    <span class="hljs-keyword">FOREIGN KEY</span> (EntryFK, PersonFK, PoolFK) <span class="hljs-keyword">REFERENCES</span> Entry(EntryTimestamp, PersonFK, PoolFK),
    <span class="hljs-keyword">CHECK</span> (
        (
            BanEndDate <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
            <span class="hljs-keyword">AND</span> BanStartDate <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
        )
        <span class="hljs-keyword">OR</span> BanEndDate &gt;= BanStartDate
    )
);
</code></pre>
<p>In its DDL, we can see that the table identification is the same as the previous ones, with a primary key composed of the foreign key pointing to Sanction, as well as another foreign key pointing to Entry (which consists of three attributes). In this case, the sanction can impose several conditions on the sanctioned user: it can either prohibit them from entering for a period of time, require them to pay compensation, or serve a certain number of community service hours.</p>
<p>So if we assume that the domain and requirements don’t force us to store NULL values in any attribute and that we can make any decision about how data is stored in the system, we’ll decide to allow BanStartDate and BanEndDate to be NULL for sanctions that don’t prohibit the sanctioned user from entering the pool. Thus, in the CHECK constraint defined at the end, we see that as an integrity condition for all tuples in the table, both attributes must be either null or the end date must be after the start date of the prohibition. This ensures that only valid data is stored in the table.</p>
<p>Lastly, we can see that some attributes of the foreign key pointing to Entry are named exactly the same as the attributes they reference, like personFK or PoolFK. This is neither a problem nor an error, although in a larger project where each table has more attributes, we should follow a proper style guide when naming attributes, especially those reserved for foreign keys. This way, we can more clearly understand their purpose without having to spend time analyzing the schema in detail.</p>
<h3 id="heading-how-to-create-the-database">How to Create the Database</h3>
<p>Now that you understand the domain semantics and have completed the <strong>conceptual</strong> and <strong>logical design phases</strong>, we can implement the logical model on the DBMS.</p>
<p>The easiest way to do this is by creating a script with a <strong>.sql</strong> extension that contains all the necessary DDL code to populate the database – that is, the statements we just reviewed where we create tables, data types, and constraints.</p>
<p>But since we aren’t working with a real project database here, we don't need to worry about the data that might be in tables that already exist in the database, especially those with the same name as any of the tables we’ll going to create. So for simplicity, before creating them, we’ll execute some DROP statements to remove tables with names matching any of the tables we are going to create. This will make sure that they contain no tuples.</p>
<p>Following this process, we’ll arrive at a DDL script <a target="_blank" href="https://gist.github.com/cardstdani/1247573e1ef2f6ea9ab99b82c5761ad6">like this</a> (it’s quite long, so I’ve left it in the gist).</p>
<p>When we run the script, keep in mind that the statements will execute one by one from top to bottom. So we first use the DROP statements to remove any tables in the database that have the same name as any of those we’ll create.</p>
<p>This process is equivalent to <strong>deleting</strong> our entire database – that is, our logical model that was once created – so we first need to remove the tables that aren’t <strong>referenced</strong> by any <strong>foreign keys</strong> to maintain integrity while deleting the remaining tables.</p>
<p>Then, under the same condition, all corresponding tables that aren’t referenced by any foreign keys are successively deleted until no tables remain to be deleted.</p>
<p>There should now be no tables in our database whose names conflict with the tables in our logical model, so we write the CREATE TABLE statements we saw earlier for each table in the logical model.</p>
<p>We also need to do this in a specific order, specifically the reverse of the deletion process. Here, we first need to create tables that don’t have any foreign keys pointing to another entity. If we create a table at the beginning that needs to reference another table that hasn't been created yet, the DBMS will generate an integrity error. So as you can see in the script, we place the statements in an order such that whenever a table with foreign keys pointing to other tables is created, those tables have already been created beforehand.</p>
<p>To figure out how we need to order both the DROP and CREATE TABLE statements, there are <a target="_blank" href="https://medium.com/%40tharinduimalka915/how-kahns-algorithm-helped-me-solve-database-schema-dependencies-2b7e54142fd5">algorithms</a> like <a target="_blank" href="https://en.wikipedia.org/wiki/Topological_sorting">topological sorting</a> that we can apply to the relational diagram. This way, we treat the database schema as a <strong>directed graph</strong> made up of <strong>nodes (tables)</strong> and <strong>directed edges (foreign keys)</strong>. With this algorithm, for example, we can progressively remove minimal or maximal nodes from the graph, creating or deleting the table they represent. But, this is not the only <a target="_blank" href="https://softwareengineering.stackexchange.com/questions/359107/resolving-foreign-keys-breaking-cycles-to-enable-a-topological-sort">method</a> available.</p>
<p>Regarding data types and constraints defined in <strong>assertions</strong> or <strong>triggers</strong>, the order of creation is easier to infer. This is because the ENUM or DOMAIN types must always be created before being used in a table's attribute declaration. So the simplest approach is to create them at the very beginning, or just before we use them for the first time (what we’ve done here).</p>
<p>On the other hand, it's best to define assertions or triggers at the end. We also want to give them names descriptive enough of the constraints they model, as their definitions may involve multiple tables that we need to create before defining the constraint. Also, since these elements don’t contain <strong>data (tuples)</strong>, we don’t need to delete them at the start of the script unless we are going to modify the schema itself. In that case, some constraints might become obsolete, meaning they access attributes or tables that no longer exist.</p>
<p>In summary, with this <strong>SQL script</strong>, we create the tables, data types, and constraints that make up our database schema, ensuring that none of them contain tuples immediately after being created.</p>
<p>But to run the script, we need to create a database in the DBMS. Let’s use the CREATE DATABASE statement to create a new database with a specific name:</p>
<pre><code class="lang-pgsql"> <span class="hljs-keyword">CREATE</span> <span class="hljs-keyword">DATABASE</span> ExampleDataBase <span class="hljs-keyword">OWNER</span> postgres;
</code></pre>
<p>If we run this command on the DBMS terminal, we will create a completely empty database named <strong>"exampledatabase"</strong>. Note that PostgreSQL is not case-sensitive for element names or SQL statements. So even if we write an element's name in uppercase, when we later check the name value stored by the DBMS for the database, we’ll see it in lowercase.</p>
<p>We can also assign an owner user, who will have all the <a target="_blank" href="https://www.postgresql.org/docs/current/ddl-priv.html">privileges</a> over that element. By default, we can make the owner user <a target="_blank" href="https://stackoverflow.com/questions/50883645/is-postgres-a-default-and-special-user-of-postgresql">postgres</a>, but we can change it later with a statement like the following:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">ALTER</span> <span class="hljs-keyword">DATABASE</span> exampledatabase
<span class="hljs-keyword">OWNER</span> <span class="hljs-keyword">TO</span> user3; <span class="hljs-comment">/*user3 is a sample user*/</span>
</code></pre>
<p>Once we’ve created the database, we can connect to it using the DBMS command <code>\c exampledatabase</code>. Finally, we can execute the <strong>.sql</strong> script with the command <code>\i /path_to_script/script.sql</code>. The DBMS should then notify us that the DROP statements have had no effect since there is no table with the corresponding name to delete (the database is empty). But, after creating the tables, if we run the script again, the <strong>DROP</strong> statements will delete them because they are created, preventing the DBMS from giving us these notifications.</p>
<p>Similarly, if any statements encounter errors that prevent their execution, or in special situations like the one we just mentioned, the DBMS will notify us – but it won’t stop the execution of the script. It will simply move on to execute the next declared statements (at the syntactic level, it executes the next statement we have separated with the corresponding <code>;</code>).</p>
<h2 id="heading-chapter-11-example-queries">Chapter 11: Example Queries</h2>
<p>Once we have done all this, we’ll have the database created and populated with tables. But these tables are empty, meaning they don't contain any tuples. So if we want to run queries on them that return any results, we need to execute INSERT statements to add tuples to all the tables.</p>
<p>In this case, since the database is an example, we don't have real data to use for populating the tables, and there's no simple and automatic way to fill them with synthetic data. The best option is to use the <strong>Python</strong> library <strong>faker</strong> and create a script to generate this synthetic data (I’ve explained this in this <strong>Jupyter Notebook</strong>).</p>
<p>There is also always the option to look for real data sources to populate our database. But when doing this, those data sources might provide information in table schemas that don't exactly match those of our database tables, requiring us to <strong>integrate</strong> and then <strong>insert</strong> the information through a process like an ETL. These <strong>ETL</strong> processes of integration and insertion are often applied in <strong>Data Warehouses</strong>, which can also be a database like ours.</p>
<h3 id="heading-running-basic-queries">Running Basic Queries</h3>
<p>So, assuming we already have the database populated with tables and tuples within them, we can run different queries on them. After all – the main operation that other services from other software layers use from the database is querying. This lets them obtain data that they can then transform, use to calculate certain metrics, or simply display to the end user.</p>
<p>For example, right after inserting the data, the first query we can run to ensure that the insertion process worked is the following:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> <span class="hljs-string">'person'</span> <span class="hljs-keyword">AS</span> tableName, COUNT(*) <span class="hljs-keyword">AS</span> numberOfTuples
<span class="hljs-keyword">FROM</span> Person;
</code></pre>
<p>As you can see, we use the FROM clause to get all the information stored in the Person table (which we could have written entirely in lowercase). Then, we use the <strong>aggregation function COUNT(*)</strong> to count the total number of tuples in the table, naming the column where this number is stored <strong>numberOfTuples</strong>.</p>
<p>But, if we also want to display the table name in the same tuple as the previous count, we can add another column in the SELECT statement where all its values are <strong>'person'</strong>. This way, when the query is executed, it will return a table with two columns, one <strong>tableName</strong> and another <strong>numberOfTuples</strong>. Since the aggregation function only returns one value, the resulting table will have only one tuple, where the tableName column will have the value 'person' and the other column will show the number of tuples in the <strong>Person</strong> table.</p>
<p>If we want to count the tuples of all the tables in the database, we have the option to create a larger query that gathers all the results of the <strong>sub-queries</strong> that count the tuples of each table. For this, we can use UNION ALL, which combines the tuples from all resulting tables into a single table. This works as long as all resulting tables have exactly the same schema, with the same column names and data types, as in this case.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> <span class="hljs-string">'person'</span> <span class="hljs-keyword">AS</span> tableName, COUNT(*) <span class="hljs-keyword">AS</span> numberOfTuples
<span class="hljs-keyword">FROM</span> Person
<span class="hljs-keyword">UNION</span> <span class="hljs-keyword">ALL</span>
<span class="hljs-keyword">SELECT</span> <span class="hljs-string">'city'</span> <span class="hljs-keyword">AS</span> tableName, COUNT(*) <span class="hljs-keyword">AS</span> numberOfTuples
<span class="hljs-keyword">FROM</span> city;
</code></pre>
<p>Lastly, when we say "obtain information" about an element of the domain or database schema in this context, we mean getting its data stored in the attributes of the table that represents it.</p>
<p>For example, information about a person could be the <strong>Name</strong> or <strong>Email</strong> attribute of the Person table, among others. We won’t detail that info here, as in most cases, it’s easy to modify which attributes are selected to return as a query result. But in a real environment, it’s convenient and important to pay attention to the <strong>attributes</strong> the query should return, the <strong>names/aliases</strong> they should have, and the <strong>order</strong> in which they should be returned. The functionality of other software layers often depends on this step being performed correctly.</p>
<h3 id="heading-tuple-filtering">Tuple Filtering</h3>
<p>The query we just looked at is useful for managing the database. Knowing how much information is stored in each table helps us make sure that certain normalization or schema transformation operations have run correctly (and even that the information itself is correct).</p>
<p>Let’s now look at some other queries that allow us to execute services provided to the end user. We use these to operate on the domain according to its semantics, so they can be very diverse. Here, we’ll distinguish between different types of queries based on their approach and the SQL tools used in their construction.</p>
<p>First, we have a series of queries for tuple filtering. These queries apply a filter on a table to keep only certain tuples that meet specific conditions. Note that the table containing the tuples we want to filter can be generated in any way, whether through a JOIN, a set operation, or whatever we want to do. But if you need to perform a grouping with GROUP BY, the resulting table must be filtered using a HAVING clause, which differs from the usual WHERE clause used to filter tuples.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> person P
<span class="hljs-keyword">WHERE</span> P.name <span class="hljs-keyword">LIKE</span> <span class="hljs-string">'Carol%'</span>;
</code></pre>
<p>The above is a simple example that retrieves the tuples from the Person table for people whose names starts with <strong>“Carol“</strong>. As you can see, the only statement we need to filter tuples is WHERE. In it, all the conditions required for filtering are defined, regardless of their number or nature, as some will be performed using subquery results.</p>
<p>In this specific case, the query has the condition that a person's name must start with exactly the string that appears in the LIKE operator. Since it’s case-sensitive, the string has to match exactly what we want to search or filter. Then all tuples that meet this condition will be returned in the resulting table. We’ll get all of its attributes because of the <strong>SELECT *</strong> notation we used.</p>
<p>To illustrate that it doesn't matter whether you use uppercase or lowercase when naming schema elements in SQL statements, we can see in the below query that both the table City and its attributes are in lowercase (except for one that’s written exactly as it was declared, with the first letter capitalized). If we run this query, it will work the same as if we use <strong>C.</strong> to reference the attributes, since using only one table means there’s no ambiguity when referring to the table's columns.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> city C
<span class="hljs-keyword">WHERE</span> (population &gt; <span class="hljs-number">20000</span> <span class="hljs-keyword">AND</span> C.Latitude &gt;=<span class="hljs-number">0</span>) <span class="hljs-keyword">OR</span> C.longitude &lt;= <span class="hljs-number">0</span>;
</code></pre>
<p>Ultimately, with these conditions, we get all the tuples from <strong>City</strong> that have a population greater than 20,000 and a positive <strong>latitude</strong>, or those that simply have a negative <strong>longitude</strong>.</p>
<p>Let’s look at a similar example: here, we get all cruise bookings with a price below 500, an even cabin number, and a payment method of cash. In this case, we can see how we can apply different types of operators to build the condition.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> cruiseBooking CB 
<span class="hljs-keyword">WHERE</span> CB.price &lt; <span class="hljs-number">500</span> <span class="hljs-keyword">AND</span> MOD(CB.cabinnumber, <span class="hljs-number">2</span>)=<span class="hljs-number">0</span> <span class="hljs-keyword">AND</span> CB.paymentmethod=<span class="hljs-string">'cash'</span>;
</code></pre>
<p>On one hand, if we want to declare that all the conditions we impose must be met, we’ll use the logical operator AND. This performs a logical conjunction of those conditions so that the selected tuple is added to the resulting table only when all of them are met at the same time.</p>
<p>In other words, we can see the WHERE clause as a logical function that runs once for each tuple present in the table we want to filter. So if the result of that logical function is TRUE, then the tuple meets the conditions. Otherwise, it’s discarded and not included in the result table of the query.</p>
<p>So now we know that all the conditions we can define in a WHERE clause must be composed of a sequence of simpler logical conditions like <strong>“CB.price &lt; 500“</strong> joined by logical operators. Also, in each of these simpler conditions, we can find more logical operators, as they’re conditions that we can see as logical functions, which can themselves be composed of a sequence of even simpler conditions joined by logical operators. This allows for recursion, enabling us to use <strong>parentheses</strong> like in <strong>(C1 AND (C2 OR C3))</strong> to adjust the <strong>priority</strong> and <strong>precedence</strong> of these operators at different levels of recursion in our condition (just like in other programming languages).</p>
<p>On the other hand, we can also encounter conditions where arithmetic or comparison operators are used, such as in this case when checking if the string containing the payment method is exactly the value <strong>‘cash‘</strong>.</p>
<p>While in other languages we might write <code>CB.paymentmethod='cash'</code>, in SQL we write the comparison operator with a single character =. If we want to negate it, we can do this either by using the logical operator NOT (affecting the entire equality condition) or by using <code>CB.paymentmethod&lt;&gt;'cash'</code> which represents the condition where it checks that the payment method is not <strong>‘cash‘</strong>, meaning it’s different from that value.</p>
<p>In addition to these operators, we also have a series of mathematical functions available. For example, to check if a number is even or odd, in most general-purpose programming languages we have the <strong>modulo operator %</strong> which calculates the remainder of dividing the number by 2 – so if it’s 0, the number is even.</p>
<p>But in SQL, these operations aren’t implemented by default with arithmetic operators, but rather with functions. Specifically, to calculate the modulo, we use <strong>MOD(Dividend, Divisor)</strong>, although there are <a target="_blank" href="https://www.postgresql.org/docs/current/functions-math.html"><strong>many other</strong></a> similar functions.</p>
<p>We can use some of the operators mentioned earlier to perform calculations using entire columns. This results in other columns containing the results of those operations.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *, (<span class="hljs-built_in">CURRENT_DATE</span> - CB.bookingDate) <span class="hljs-keyword">AS</span> DateDifference1, ABS(CB.ArrivalDateFK-CB.DepartureDateFK)
<span class="hljs-keyword">FROM</span> cruiseBooking CB;
</code></pre>
<p>For example, in this query, we want to calculate several date differences, one being the number of days between the booking date and the current date, and another being the number of days between the departure and arrival dates of the cruise trip.</p>
<p>To do this for each tuple in the CruiseBooking table, the simplest way is to add several columns that take the results of these calculations as their values. Specifically, we create these columns in the SELECT statement. This selects the corresponding attributes from the resulting table of the query and displays them to the user. Only those attributes are visible to the user, even though we got them from a table with more attributes.</p>
<p>But, besides selecting attributes, we can also define new columns that didn't exist in the table we’re selecting from. For example, in this query, using the notation *, we select all the attributes present in the table from the FROM statement, which in this case is <strong>CruiseBooking</strong>.</p>
<p>In addition to those, we concatenate more attributes with a comma, like <strong>DateDifference1</strong> or the difference between the departure and arrival dates of the corresponding trip. If we look at the result of the query after adding these additional attributes, we’ll see a new column in the resulting table called <strong>DateDifference1</strong>, which will take as values the difference between the current date gotten with <strong>CURRENT_DATE</strong> and the booking date, which is <strong>CB.bookingDate</strong>.</p>
<p>So we see that in the SELECT statement, we can perform operations with the values of the tuples to generate new columns with intermediate calculations, or simply calculations required by the query, as in this case.</p>
<p>Specifically, the operation performed on each tuple to generate the value of the new column is defined in the SELECT statement itself. In this case, with <strong>CURRENT_DATE - CB.bookingDate</strong>, we define that the value of each tuple equals the current date minus the booking date. By default in SQL this returns the difference in days between the two dates.</p>
<p>Then to get the difference between the departure and arrival dates of the cruise trip, we use the values of the <strong>DepartureDateFK</strong> and <strong>ArrivalDateFK</strong> attributes from the foreign key pointing to Voyage. This avoids having to query data from other tables that contain them.</p>
<p>If we simply subtract them, depending on the order, we could get negative results, since one date is earlier than the other. So if we just want the absolute difference, we can wrap the operation with the <strong>ABS()</strong> function. And if we don't assign a specific name to that additional column, SQL by default assigns it the name <strong>“abs“</strong>. But we’ll want to change it sooner or later to avoid ambiguity problems if we use the <strong>ABS()</strong> function again to create another new column.</p>
<p>In the previous query, we saw that all the information we needed was present in the CruiseBooking table from the FROM clause – but this is not always the case.</p>
<p>For example, in the below query, we want to do a few things: first, we want to get all the bookings made by people whose names start with a letter that is later or equal to <strong>‘L’</strong>. They should also meet a series of conditions like the ones we saw before. Finally, we want to calculate the difference in days between the current date and the booking date as we saw before.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *, (<span class="hljs-built_in">CURRENT_DATE</span> - CB.bookingDate) <span class="hljs-keyword">AS</span> DateDifferenceColumn 
<span class="hljs-keyword">FROM</span> cruiseBooking CB <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P <span class="hljs-keyword">ON</span> CB.PersonFK = P.PersonID
<span class="hljs-keyword">WHERE</span> CB.price &lt; <span class="hljs-number">2000</span>
    <span class="hljs-keyword">AND</span> MOD(CB.cabinnumber, <span class="hljs-number">2</span>) = <span class="hljs-number">0</span>
    <span class="hljs-keyword">AND</span> CB.paymentmethod = <span class="hljs-string">'cash'</span>
    <span class="hljs-keyword">AND</span> CB.bookingDate <span class="hljs-keyword">BETWEEN</span> <span class="hljs-string">'2025-01-01'</span> <span class="hljs-keyword">AND</span> <span class="hljs-built_in">CURRENT_DATE</span>
    <span class="hljs-keyword">AND</span> P.Name &gt; <span class="hljs-string">'L'</span>;
</code></pre>
<p>For this, if we only use the CruiseBooking table in the FROM clause, we won't be able to access the name of the person who made the booking, as that’s an attribute of the Person table. We can get information from that table using the foreign key PersonFK from CruiseBooking. So to use the Name attribute from the Person in our query, we need to somehow "concatenate" or join the columns of the Person table with the information from the CruiseBooking table that we had before.</p>
<p>In SQL, the JOIN operation allows us to do this. We just need to choose a type and conditions that let us obtain only the tuples with the information we want.</p>
<p>Among all the types of JOINs, the least likely to be used in production or in complex queries is the <strong>implicit join</strong>. When we use an <strong>implicit join</strong>, we are performing a Cartesian product between all the tuples involved in that JOIN. So if we want to keep only certain tuples from that Cartesian product, we have to use a WHERE clause to impose certain conditions on the attributes.</p>
<p>Implicit joins are harder to read and maintain. In large or complex queries, we need to separate the join itself from the conditions on the Cartesian product. That means the logic is split between the FROM list and the WHERE clause, so you have more places to check when you modify or refactor the query.</p>
<p>Also, in implicit JOINs, we can’t perform operations equivalent to an OUTER JOIN because there’s no way to fill certain attributes with NULL if they’re not referenced in the other table of the JOIN (among other disadvantages). So the type of JOIN we choose will depend on the condition we need to impose on the tuples of the Cartesian product.</p>
<p>Just keep in mind that there are certain cases where it might be convenient to use <strong>implicit joins</strong>, such as in queries involving very few tables (at most 2 to keep the code as simple as possible) with simple restrictions, or when maintaining <a target="_blank" href="https://www.ibm.com/think/topics/legacy-code"><strong>legacy code</strong></a>, meaning old or inherited code that uses implicit joins.</p>
<p>In this case, when performing the Cartesian product, we’ll get a series of tuples that combine all those from CruiseBooking and Person. This will result in tuples with information about these two tables where the person's information does not correspond with the person referenced by the foreign key of the CruiseBooking tuple.</p>
<p>For that reason, we don't need those tuples from the Cartesian product – or in other words, we want to get all those where the foreign key PersonFK of CruiseBooking points to the person whose information is indeed in that same tuple of the Cartesian product.</p>
<p>Formally, we express this condition as <strong>CB.PersonFK = P.PersonID</strong>. In this case, we need to assign alias names to the tables to differentiate their attributes and resolve possible ambiguity issues. So the most suitable type of JOIN for this query is an INNER JOIN, as it allows us to declare this equality condition exactly as we have written it here in an ON clause, as seen above.</p>
<p>In this way, by using a specific type of JOIN that’s not implicit, we can isolate all the filtering conditions of the tuples in the WHERE clause (dedicating the FROM to obtaining the data). Through the JOIN, we can concatenate the attributes of other tables to the resulting table of the query, and apply a specific filter to the tuples of the Cartesian product of that operation with an equality condition.</p>
<p>Regarding the WHERE conditions in this query, we’ve added one that makes sure the booking date is between <strong>'2025-01-01'</strong> and the current date we get with <strong>CURRENT_DATE</strong>. We could’ve used the arithmetic operators &lt;= and &lt;= for this, but SQL offers us a more convenient alternative using <strong>BETWEEN</strong>, where we define that the date of the <strong>bookingDate</strong> attribute must be between <strong>'2025-01-01'</strong> and <strong>CURRENT_DATE</strong>, both included.</p>
<p>The BETWEEN operator would also work to check if a string is between a pair of strings, all compared alphabetically. In this query, the only condition we impose on the lexicographical order of a string is <strong>P.Name &gt; 'L'</strong>. This ensures that the name of the person who made the booking starts with a letter <strong>greater than or equal</strong> to <strong>L</strong>. (If their name is composed of text that starts with <strong>L</strong> followed by more letters, that text will automatically be considered strictly greater than the text <strong>'L'</strong>.)</p>
<p>If we wanted to keep only the people whose names start strictly with a letter greater than L, we would have to use the condition <strong>P.Name &gt; 'M'</strong>.</p>
<p>What if we need to get a list of all the people in the database, their information, and also the details of all the cruise bookings they have made? We’d need a list where all the registered people in the database appear.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> cruiseBooking CB <span class="hljs-keyword">RIGHT JOIN</span> Person P <span class="hljs-keyword">ON</span> CB.PersonFK = P.PersonID
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> P.PersonID;
</code></pre>
<p>For example, if someone has made 2 bookings, there will be 2 rows with their information plus the details of the two bookings they made. Meanwhile, people who have never made a booking will appear in the list with a row containing their information and a series of NULL values in the columns where the booking information would be.</p>
<p>This query isn’t common in real cases, but this structure can be useful for solving other types of queries. So to build this list, the first operator we might think of is an OUTER JOIN. In this type of join, we specify the side of the table whose rows should always appear in the final list, filling in with nulls in the other table when necessary.</p>
<p>To understand this, in this example, we see that a person doesn’t have to have any associated booking – so for each person, there doesn't necessarily have to be a booking in their name. So there may be some people who don’t have any bookings associated with them. So when we’re trying to do an INNER JOIN with the CruiseBooking table, they won't appear in the resulting table from the query.</p>
<p>That's why, instead of an INNER JOIN where we impose a strict condition that all tuples from the operation must meet, we use an OUTER JOIN. So, if we want all people to appear in the list even if they haven't made any bookings, we need to specify the side of the OUTER JOIN where we placed the Person table in the JOIN operation.</p>
<p>In this case, the Person table is on the right side, meaning its attributes are concatenated to the right of those in the CruiseBooking table. So in the OUTER JOIN, we must specify the RIGHT side so that all tuples from the table on the right side appear in the list, and for those people who don't have any associated bookings, their corresponding tuple will be filled with NULL values in the respective attributes that hold booking information.</p>
<p>If we had placed the Person table on the left side, then to achieve the same result as the previous query but with the columns of both tables reordered, we just need to change <strong>RIGHT</strong> to <strong>LEFT</strong> in the JOIN operation. This way, all tuples from the table on the left (meaning Person) must appear in the resulting table. The right side gets filled in with NULL values in this case, since that's where the attributes of the CruiseBooking table are.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P <span class="hljs-keyword">LEFT JOIN</span> cruiseBooking CB <span class="hljs-keyword">ON</span> CB.PersonFK = P.PersonID
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> P.PersonID;
</code></pre>
<p>On the other hand, in both queries, you can see that we used ON to define the equality condition on the tuples of the Cartesian product produced by JOIN. We have to do this because if we use USING instead of <strong>ON</strong>, both attributes on which we want to impose the equality condition must be named exactly the same – so we can’t use <strong>USING</strong> here.</p>
<p>Aside from the JOIN operation from which the data is extracted, we often need to return the result sorted by an attribute. It may also simply be useful to have the result sorted so we can make checks more quickly, as in this case.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.Birth
<span class="hljs-keyword">FROM</span> Person P <span class="hljs-keyword">LEFT JOIN</span> cruiseBooking CB <span class="hljs-keyword">ON</span> CB.PersonFK = P.PersonID
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> P.PersonID;
</code></pre>
<p>To do this, at the end of the query, we can add an ORDER BY statement, which sorts the tuples of the resulting table according to the PersonID attribute of the person. This attribute doesn’t need to appear in the SELECT, as we might need other attributes that aren’t the ones defining the order, as shown above.</p>
<p>To finish with this type of JOIN, besides defining one side as RIGHT or LEFT, in an OUTER JOIN we might also need all the tuples from both sides' tables to appear. In the query below, for example, we need to get a list of all driving license applications, so that all of them appear, one in each tuple, with all the information regarding their rejection or acceptance.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> DrivingLicense D <span class="hljs-keyword">FULL</span> <span class="hljs-keyword">OUTER</span> <span class="hljs-keyword">JOIN</span> RejectedDrivingLicense R <span class="hljs-keyword">USING</span> (LicenseID);
</code></pre>
<p>To resolve this query, first, keep in mind that the schema constraints prevent us from having a driving license application both accepted and rejected at the same time. So for each application registered in the database, there will be either a tuple in RejectedDrivingLicense or in DrivingLicense, depending on whether it has been rejected or not. So when obtaining the query list, if the resulting table contains all the attributes from both tables, there will always be NULLs in some of them (either in RejectedDrivingLicense or in DrivingLicense).</p>
<p>To make sure that all applications appear, we can perform a FULL OUTER JOIN, where the OUTER specification is optional as we have seen on other occasions. This forces the tuples from both tables to appear in the final result, filling with NULL on the corresponding side for each tuple.</p>
<p>For example, if a license is accepted and we try to find it in the <strong>RejectedDrivingLicense</strong> table, it clearly won't be there. So, if we did an <strong>INNER JOIN</strong>, we wouldn't get a tuple for that application, which happens similarly with rejected applications and the DrivingLicense table. So with a <strong>FULL OUTER JOIN</strong>, we ensure that all applications appear, filling with <strong>NULL</strong> in RejectedDrivingLicense when the application is accepted and in the other table when it’s rejected. In this case, its also possible to use USING in the JOIN, since the equality condition is based on attributes in different tables that have exactly the same name.</p>
<p>Another JOIN we might encounter in real queries is the <strong>NATURAL JOIN</strong>, which is very similar to the INNER JOIN but with simpler syntax.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> PersonFK, RequestDate, Fee, ApprovalDate, Points
<span class="hljs-keyword">FROM</span> DrivingLicenseRequest <span class="hljs-keyword">NATURAL</span> <span class="hljs-keyword">JOIN</span> DrivingLicense;
</code></pre>
<p>For example, you can see in the example above a query that can help us verify that the schema's integrity constraints are met. In it, we get a list of all driving license requests that have been approved.</p>
<p>To do this, we perform a <strong>NATURAL JOIN</strong> between the <strong>DrivingLicense</strong> table and its superclass <strong>DrivingLicenseRequest</strong>. Since the only attributes with equivalent names are <strong>LicenseID</strong>, SQL automatically imposes the condition that the tuple with information from both tables has the same values in the LicenseID attributes of both tables, removing both attributes from the resulting table of the query.</p>
<p>This automatically imposed condition, as well as removing the attributes, is what characterizes the NATURAL JOIN. It’s often be preferable to an INNER JOIN because of these characteristics. By eliminating identical attributes, we eep the information that actually represents the people in those tuples. We can then use it to calculate various metrics or even as the result of a subquery in a more general query.</p>
<p>In this specific case, since all accepted requests have to be recorded in the DrivingLicenseRequest table, this query should return all tuples from DrivingLicense. But if any aren’t recorded in DrivingLicenseRequest, the foreign key won’t reference any valid tuple in DrivingLicenseRequest, revealing a database integrity issue.</p>
<p>Fortunately, we never have to manually check this situation with these queries, as the DBMS automatically verifies that all <strong>integrity constraints</strong> are met with each database modification, especially those related to keys.</p>
<p>In real queries, <strong>multiple JOIN</strong> operations are usually used in the same FROM statement because we need to gather data from multiple tables (or even from within the same table).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Residence R1 <span class="hljs-keyword">ON</span> (P.PersonID = R1.PersonFK)
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Residence R2 <span class="hljs-keyword">ON</span> (
        P.PersonID = R2.PersonFK
        <span class="hljs-keyword">AND</span> R1.CityFK &lt;&gt; R2.CityFK
    )
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> P.personID;
</code></pre>
<p>For example, say we want to find people who have lived in several different cities at some point in their lives, regardless of when they did so. Since our schema lets people live in multiple cities at once, we’ll have to use several JOIN operations to gather data from <strong>Person</strong> and <strong>Residence</strong> and join them.</p>
<p>But given the condition we impose on the people, to know if someone has lived in more than one city, we need to check the Residence table and see if there are multiple Residence tuples for the same person with different cities.</p>
<p>Specifically, the query we want to make should get all those people who have lived in at least two <strong>different</strong> cities. If we only impose the condition that a person appears in at least two tuples of the <strong>Residence</strong> table, we’d get people who have had at least two residences – not those who have lived in different cities in those residences.</p>
<p>Therefore, the final condition ends up being that the person appears in at least two tuples of <strong>Residence</strong> where the associated city they have lived in is <strong>different</strong> in both tuples. Also, by checking this condition, we aren’t ensuring that the person only has those two tuples – we just need to know if they appear in at least two tuples with the previous characteristics (as a person may have had many residences).</p>
<p>To implement this query, we might first think of using set operations and subqueries – but there is a way to solve it using only JOIN operations.</p>
<p>When we do a JOIN between two tables, we are really doing the Cartesian product, from which we only keep some tuples that meet certain conditions. For example, when doing a JOIN between <strong>Person</strong> and <strong>Residence</strong>, the foreign key <strong>PersonFK</strong> in Residence must refer to the person from that same tuple in the <strong>Cartesian product</strong>. This means it must match the PersonID attribute from the Person table. With this, we can see that we obtain all the residences each person has or has had.</p>
<p>Then, from all of them, if we want to check that there are at least two with different <strong>foreign key CityFK</strong> values (meaning that there are two residences in different cities), we can do another JOIN of the intermediate table resulting from the previous JOIN with the Residence table.</p>
<p>This way, in addition to saying that its <strong>foreign key</strong> PersonFK has to refer to the corresponding person from each tuple resulting from the JOIN, we’re also declaring that the city it refers to must be different from the city referenced by the previous Residence table used in the previous JOIN.</p>
<p>To understand this in a more programmatic way, when doing a JOIN between Residence and itself, we’re getting tuples that represent <strong>pairs of residences</strong>. So we’re obtaining a series of tuples that together represent the Cartesian product between the tuples of the Residence table with themselves.</p>
<p>In other words, we end up with a series of tuples where, in each one, we can find information from exactly 2 tuples of the Residence table, for each possible pair of Residence tuples (including cases where both tuples are the same). If we add the restriction that these pairs must refer to a certain person, then they will be all the possible pairs of residences that a person has had.</p>
<p>Then if we also add the condition that for each pair of residences the cities they refer to must be different, we‘ll end up with tuples where the person who has had those residences have lived in at least two different cities. This doesn’t ensure that it’s exactly two, as they may have lived in many more (which we can see in the resulting tuples from these JOIN operations).</p>
<p>When implementing this in SQL, we see that in both ON clauses, we declare the condition that the Residence tuples must refer to the same person of the tuple we want to construct – with that person and a pair of their residences. Also, in the second JOIN, we declare the condition that the cities of the pair of residences must be different using the operator &lt;&gt;. Finally, we order the result according to the values of the PersonID attribute.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">DISTINCT</span> P.Name
<span class="hljs-keyword">FROM</span> Person P
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Residence R1 <span class="hljs-keyword">ON</span> (P.PersonID = R1.PersonFK)
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Residence R2 <span class="hljs-keyword">ON</span> (
        P.PersonID = R2.PersonFK
        <span class="hljs-keyword">AND</span> R1.CityFK &lt;&gt; R2.CityFK
    )
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> P.personID; <span class="hljs-comment">/*Error*/</span>
</code></pre>
<p>As you can see from the query result, there are people who have had many residences, resulting in many pairs of residences that meet the imposed conditions. This creates multiple tuples in the resulting table where the same person's information appears.</p>
<p>So, if we only want to get the person's name, we can replace * with <strong>P.Name</strong> in the <strong>SELECT</strong> statement to select only that attribute. To avoid duplicate values, we can use <strong>DISTINCT</strong>. Without DISTINCT, the same person's name may appear multiple times, depending on the number of residence pairs they have had in different cities. This also happens because SQL by default models tables with multisets, allowing such duplicates.</p>
<p>If we care about removing duplicates, we should use DISTINCT – but this decision can affect other statements like <strong>ORDER BY</strong>. In this example, we’re ordering by the values of the PersonID attribute, which we don't need in the resulting table where only the Name attribute appears.</p>
<p>Since <strong>PersonID</strong> doesn’t appear in the SELECT after using DISTINCT, the DBMS will give us an error. We have several options to fix it.</p>
<p>On one hand, we can remove DISTINCT, which will result in duplicate person data but that’s ordered by their PersonID (even though it won't be shown in the result).</p>
<p>On the other hand, we can keep DISTINCT and remove ORDER BY, because if the attribute we are ordering by does not appear in the SELECT after using DISTINCT, we will get an error that will prevent us from executing the query.</p>
<p>Another alternative we have is to show all the information about the person, not just the name. This way, we can order the result by the PersonID attribute and remove duplicate people. Instead of writing the entire list of attributes from the Person table in the SELECT, we can use the notation <strong>P.*</strong> to refer to <strong>all the attributes of the table with alias P</strong>.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">DISTINCT</span> P.*
<span class="hljs-keyword">FROM</span> Person P
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Residence R1 <span class="hljs-keyword">ON</span> (P.PersonID = R1.PersonFK)
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Residence R2 <span class="hljs-keyword">ON</span> (
        P.PersonID = R2.PersonFK
        <span class="hljs-keyword">AND</span> R1.CityFK &lt;&gt; R2.CityFK
    )
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> P.personID;
</code></pre>
<p>Finally, in SQL, it's common to encounter queries where we need to work with dates. For example, in our schema, we might have a query to get all the people who were born in May.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *, EXTRACT(<span class="hljs-type">MONTH</span> <span class="hljs-keyword">FROM</span> Birth) <span class="hljs-keyword">AS</span> BirthMonth
<span class="hljs-keyword">FROM</span> Person
<span class="hljs-keyword">WHERE</span> EXTRACT(<span class="hljs-type">MONTH</span> <span class="hljs-keyword">FROM</span> Birth) = <span class="hljs-number">5</span>;
</code></pre>
<p>We can solve this by imposing a single condition on the birth date, with the peculiarity that we can't treat the data type exactly as if it were entirely numeric or text. Instead, we need to extract <a target="_blank" href="https://www.w3schools.com/sql/func_mysql_extract.asp">characteristics</a> from the date to operate with.</p>
<p>In this case, the clearest characteristic to obtain is the month. By using the EXTRACT() function and the MONTH characteristic, we extract the month number from the Birth attribute's date to check if it’s May or not.</p>
<p>Note that the function generally returns numbers for day, month, year, and so on, not strings. So we treat the month as if it were a number from 1 to 12.</p>
<p>We can convert between number and string <a target="_blank" href="https://learn.microsoft.com/en-us/sql/t-sql/functions/cast-and-convert-transact-sql?view=sql-server-ver17">using other SQL tools</a>, all in the appropriate format according to the time zone and geographic area. Then, if we want that date characteristic to appear as an additional attribute in the resulting table, we simply treat the EXTRACT() function as if it were any SQL function that returns a value when given certain values from a tuple.</p>
<p>But even if we assign it an alias, we can’t use that alias in the WHERE clause to declare the condition that it equals to be 5. Instead, we must write the entire calculation in the WHERE clause. Although this may seem inefficient in terms of readability, without using additional <a target="_blank" href="https://www.freecodecamp.org/news/mysql-common-table-expressions/"><strong>Common Table Eexpression (CTE)</strong> techniques</a> like those we will see later, we have no choice but to duplicate the attribute calculation in the WHERE clause if we want to impose a condition on it.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *, EXTRACT(<span class="hljs-type">WEEK</span> <span class="hljs-keyword">FROM</span> Birth)
<span class="hljs-keyword">FROM</span> Person;
</code></pre>
<p>In addition to the day, month, and year, the <strong>EXTRACT()</strong> function allows us to obtain all kinds of characteristics from a date, like the week number with <strong>WEEK</strong> as shown above, or the current quarter number with <strong>QUARTER</strong>.</p>
<h3 id="heading-subqueries">Subqueries</h3>
<p>There are some SQL queries that require subqueries. A subquery is simply a query inside another query. It helps you solve a smaller problem so the main query can solve a bigger one.</p>
<p>Let’s dive in a little deeper. When you run a query in SQL, you get a result table (a multiset, since rows can repeat). A subquery lets the outer query use that result – for example, to check membership or existence.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P
<span class="hljs-keyword">WHERE</span> P.PersonID <span class="hljs-keyword">IN</span> (<span class="hljs-keyword">SELECT</span> PersonFK <span class="hljs-keyword">FROM</span> Residence);
</code></pre>
<p>This returns every person whose identifier appears in Residence.PersonFK – that is, everyone who has (or had) a recorded residence. The subquery produces the set of referenced person IDs, while the outer query keeps rows where p.PersonID is in that set.</p>
<p>Note that this is a <a target="_blank" href="https://www.ibm.com/docs/en/db2-for-zos/12.0.0?topic=subqueries-correlated-non-correlated">non-correlated subquery</a> (it doesn’t reference the outer query), which many databases may <strong>materialize once</strong> or rewrite as a <strong>semi-join</strong> before applying the IN filter. In practice, this is usually comparable to an equivalent EXISTS or JOIN-based formulation. We’ll just choose the form that’s clearest and add appropriate indexes (for example, Residence(PersonFK), Person(PersonID)) for speed.</p>
<p>If the subquery can return NULL, IN uses three-valued logic. With a foreign key on Residence.PersonFK, NULL values are typically disallowed, so this isn’t an issue.</p>
<p>On the other hand, we can solve the query using JOIN operations as shown below:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">DISTINCT</span> P.*
<span class="hljs-keyword">FROM</span> Person P <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Residence R <span class="hljs-keyword">ON</span> R.PersonFK = P.PersonID;
</code></pre>
<p>Here, we combine the data from Person and Residence using the equality condition that requires the foreign key of Residence to reference the person in the same tuple of the Cartesian product. This way, we only get those tuples that have the information of a residence and the person associated with it.</p>
<p>Then, to keep only the data of the people, we use P.* as before – but here we need to use DISTINCT, since a person may have multiple residences. Specifying DISTINCT prevents this from duplicating the data of the same person.</p>
<p>The JOIN operation is often considered inefficient because it’s a Cartesian product that must construct all tuples of that product and then filter them using the conditions we declare. But we can make it faster with the right hardware, like <a target="_blank" href="https://arxiv.org/html/2406.13831v1"><strong>GPUs</strong></a>.</p>
<p>Still here, we need to remove duplicates with DISTINCT, which involves additional processing of the query result. We also need another filter or process that eliminates duplicate tuples, so it seems less efficient at first glance.</p>
<p>But depending on how the DBMS implements these operations at a physical level, it can be more or less efficient than using subqueries (as the hardware also makes a difference).</p>
<p>Here’s another construction based on subqueries that we can use to solve the previous query. As you can see, we build a <strong>correlated subquery</strong> where we use the PersonID attribute from the "higher-level" query to get all the residences (tuples) from the Residence table that belong to the person indicated by the PersonID identifier. In other words, since the WHERE clause is executed for each tuple of Person, we can construct a subquery where, given a certain person with that identifier, we can get all the residences registered in their name. That would be those whose foreign key PersonFK refers to the PersonID identifier of the person.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> Residence R
        <span class="hljs-keyword">WHERE</span> R.PersonFK = P.PersonID
    );
</code></pre>
<p>With this correlated subquery, SQL must build its result for each person in the Person table, as the result depends on the specific person being processed. So to only keep those people who have a residence, we use the <strong>EXISTS</strong> operator to verify that the resulting multiset of the subquery contains at least one tuple (indicating that the person has a residence).</p>
<p>SQL has to go through the Residence table for each person in the Person table, although it only goes through Residence until it finds the first tuple whose foreign key points to the corresponding person. This avoids unnecessary checks of the rest of the tuples in <strong>Residence</strong> because <strong>EXISTS</strong> only requires at least one tuple in the subquery.</p>
<p>Still, in the <a target="_blank" href="https://medium.com/learning-data/understanding-algorithmic-time-efficiency-in-sql-queries-616176a85d02"><strong>worst-case scenario</strong></a>, it would have to go through the entire table for each person if no person has or has had residences.</p>
<p>Another way we can use membership or existence operators is on a list of values. This is declared very similarly to a tuple and a subquery but is not necessarily a tuple or a subquery.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Pool P
<span class="hljs-keyword">WHERE</span> Status <span class="hljs-keyword">IN</span> (<span class="hljs-string">'closed'</span>, <span class="hljs-string">'renovation'</span>)
    <span class="hljs-keyword">AND</span> mindepth <span class="hljs-keyword">IN</span> (
        <span class="hljs-keyword">SELECT</span> mindepth
        <span class="hljs-keyword">FROM</span> Pool
        <span class="hljs-keyword">WHERE</span> mindepth &gt; <span class="hljs-number">4</span>
    );
</code></pre>
<p>For example, above we have a query that returns all pools whose status is ‘closed’ or ‘renovation’ and whose minimum depth is greater than 4.</p>
<p>To check the first condition, we could easily use the logical OR operator and declare two simpler conditions to check whether the Status value is either <strong>‘closed’</strong> or <strong>‘renovation’</strong>. But we can do this more simply using the IN operator. So by using the notation <strong>('closed', 'renovation')</strong>, we declare a list with those two values, checking with IN if the value contained in the Status attribute is in the list or not. This has the same effect as using the OR operator, but with clearer syntax and similar efficiency.</p>
<p>This check we do with IN is like a membership check on the result of a subquery, as the syntax is very similar. But don’t confuse the list declaration with a subquery, since <strong>('closed', 'renovation')</strong> doesn’t represent a multiset with tuples, but rather a list of values. We can also view it as if it were a column on which we perform a check.</p>
<p>On the other hand, the simplest way to check if the pool's minimum depth is greater than 4 is with the condition <strong>mindepth &gt; 4</strong> directly. But to show an equivalent way of checking with subqueries, you can see above that the subquery for the condition retrieves all mindepth values from the Pool table that are strictly greater than 4. Then it uses IN to check if the mindepth value from the outer query's Pool table is in the subquery's result.</p>
<p>So instead of writing mindepth &gt; 4 directly, the subquery first selects all mindepth values greater than 4, and the outer query uses IN to keep a pool row only if its mindepth is in that set. In practice, although this can also be a solution to the query, we should keep the code as simple as possible. We generally avoid these techniques.</p>
<p>Also, we don’t need <strong>alias P.</strong> to refer to the mindepth of the outer query – as it’s the only one called that way in this query. But if we had to use it in the subquery, we’d need to use the alias P. to distinguish it from the mindepth attribute of the <strong>Pool</strong> table in the subquery. (This also doesn’t need an alias because it’s a simple subquery without another subquery inside it. This is possible to do, and sometimes even necessary.)</p>
<p>Here’s another equivalent way to solve the query using subqueries:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Pool P
<span class="hljs-keyword">WHERE</span> Status <span class="hljs-keyword">IN</span> (<span class="hljs-string">'closed'</span>, <span class="hljs-string">'renovation'</span>)
    <span class="hljs-keyword">AND</span> P.mindepth &gt; <span class="hljs-keyword">ALL</span> (
        <span class="hljs-keyword">SELECT</span> mindepth
        <span class="hljs-keyword">FROM</span> Pool
        <span class="hljs-keyword">WHERE</span> mindepth &lt;= <span class="hljs-number">4</span>
    );
</code></pre>
<p>The main difference is that here, the subquery gets all the mindepth values that are &lt;=4, which is the opposite condition of what we want the tuples to meet. So in the outer query, we have the result of this subquery, which includes all the mindepth values we’re not interested in.</p>
<p>To check if a tuple meets the condition of having a minimum depth &gt;4 using these values, we use the <strong>&gt; ALL</strong> operator to verify if the mindepth of the tuple we are checking is strictly greater than all the values present in the subquery.</p>
<p>This equivalent way of solving the query is more elaborate than the simplest and most efficient solution, which is to use the <strong>mindepth&gt;4</strong> condition directly. This is simply an example to demonstrate that there's often more than one way to get the <strong>same result</strong> for <strong>any state</strong> of the database. This is the definition of <strong>equivalent queries</strong>.</p>
<p>Also, in many situations, it’s useful to use operators like ANY, IN, ALL, EXISTS, and so on in combination with other arithmetic operators on a subquery to define conditions that certain tuples must meet, as shown in these examples.</p>
<p>So far, we’ve seen queries that use subqueries in their implementation, but those subqueries essentially behave as if they were queries themselves. This means we can execute them directly on the DBMS as if they were regular queries. So nothing prevents a subquery from being made up of subqueries at a "lower" level, meaning subqueries that are at a <strong>nesting level</strong> below the other <strong>subquery</strong>, which in turn is at a lower nesting level than the <strong>query</strong> it’s in.</p>
<p>Basically, SQL allows us to chain as many subqueries as we want within a query or subquery. This helps us solve problems like the query below, which retrieves a list with information on all the people who don’t have a valid driver's license:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Person P
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> DrivingLicense D
        <span class="hljs-keyword">WHERE</span> D.LicenseID <span class="hljs-keyword">IN</span> (
                <span class="hljs-keyword">SELECT</span> LicenseID
                <span class="hljs-keyword">FROM</span> DrivingLicenseRequest R
                <span class="hljs-keyword">WHERE</span> R.PersonFK = P.PersonID
            )
    );
</code></pre>
<p>We could approach this query so that it'd require JOIN operations to solve it. But in this case, it’s structured in a "nested" manner at the subquery level so that it requires the use of subqueries.</p>
<p>So to get this list, we first go through all the people in the Person table. For each one, we check that there is no driver's license whose associated request was created by that person. We can implement this condition by applying the <strong>NOT EXISTS</strong> operator to a subquery that returns all valid driver's licenses associated with a person. We get these by filtering DrivingLicense to licenses whose matching DrivingLicenseRequest row has PersonFK = P.PersonID – that is, licenses requested by the current person.</p>
<p>Regarding this last point, as you can see in the code, the simplest way to implement it with subqueries is to check that the LicenseID of the valid driver's license exists in the set of LicenseID values from the requests in the DrivingLicenseRequest table whose foreign key points to the person being iterated over in Person. That makes this subquery <strong>correlated</strong> with the outer query we are making, as it includes the attribute <strong>P.PersonID</strong>.</p>
<p>In short, we’ve implemented this query by <strong>nesting subqueries</strong>, where SQL allows us to reach an arbitrary level of nesting according to the needs of the query. But we could’ve done it in other ways like using JOIN operations, which in certain situations are easier to understand than the approach we just followed.</p>
<p>Just remember that nesting queries is not always the best way to solve a problem, especially when multiple levels of nesting are created (whether correlated or not with each other). We’re just showing what’s possible here. It’s only worthwhile when it improves the efficiency or clarity of the query sufficiently compared to other alternatives.</p>
<p>Let’s talk about where or in which statement subqueries can be nested. In the below code, you can see how the subquery is nested in the FROM clause.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.Name
<span class="hljs-keyword">FROM</span> Person P
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> (
        <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">DISTINCT</span> PersonFK
        <span class="hljs-keyword">FROM</span> Rental
    ) R <span class="hljs-keyword">ON</span> R.PersonFK = P.PersonID;
</code></pre>
<p>Since it returns a table with tuples, we’ll often use that query result in a FROM clause to get the information from the tuples and return it to the user through a SELECT. Or we could even combine it with another table using a JOIN operation, as in this case. Specifically, this query will get information about all the people who have rented a bike at some point at least one.</p>
<p>So the approach we follow to resolve the query is to perform a JOIN between the Person table (that contains all the people in the system) and a table that has the identifiers of the people pointed to by the <strong>foreign key</strong> <strong>{PersonFK}</strong> of any tuple in Rental. This means anyone whose identifier is referenced by any tuple in Rental, implying that they’ve rented a bike at least once.</p>
<p>We can construct this list of person identifiers using a subquery that extracts all the PersonFK values from the Rental table while removing duplicates. A person may have made an arbitrary number of rentals throughout their history, but we’re interested in whether they have made at least one. So, we simply need to know if they appear in the list of PersonFK values.</p>
<p>Then, using an <strong>INNER JOIN</strong>, we combine the information of PersonFK returned by the subquery with the tuples from the Person table. This gives us all the information of the people identified by <strong>PersonFK</strong>, which in turn points to <strong>PersonID</strong>. But since we want, for example, the names of the people and not just their identifiers, both the <strong>JOIN</strong> and the <strong>subquery</strong> are essential, because if we only needed the identifier, it would be enough to return what the subquery provides.</p>
<p>In addition to nesting subqueries in the FROM clause, we can also do it in the SELECT clause, where the main goal is to calculate a metric or get more information for each tuple in the query. That is, if in the SELECT we get attributes <strong>P.PersonID</strong> and <strong>P.Name</strong> from each of the tuples returned to the user, we might want to get more information beyond these two attributes that needs to be calculated with a query. In this case, this query will be nested as a subquery in the SELECT, and it’s result will be the value added to the additional attribute representing the subquery in the SELECT.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.PersonID,
    P.Name,
    (
        <span class="hljs-keyword">SELECT</span> COUNT(*)
        <span class="hljs-keyword">FROM</span> Residence R
        <span class="hljs-keyword">WHERE</span> R.PersonFK = P.PersonID
    ) <span class="hljs-keyword">AS</span> NumResidences
<span class="hljs-keyword">FROM</span> Person P;
</code></pre>
<p>In these cases where the subquery is nested in the SELECT statement, the subquery must meet a basic requirement: it has to return at most one tuple and one column. This is because the result of the subquery will be added in a new <strong>additional column (and only one)</strong> in our SELECT. Then we’ll calculate its result and add it in each tuple of the outer query – so the subquery can’t return more than one tuple.</p>
<p>For example, in this query, we want to list all the people in the database along with a column that contains the number of residences they have had. To solve this, the simplest approach is to go through all the tuples of Person and, for each one, count how many tuples of Residence have their foreign key PersonFK referencing that person.</p>
<p>Going through the tuples of Person is simple: we just use a combination of SELECT and FROM. But in order to count how many tuples of Residence meet this condition for each person, we need a correlated subquery – specifically with the person being processed. We can uniquely identify this with P.PersonID.</p>
<p>We need to do this because to count tuples in Residence, we have to compare the values of their foreign key PersonFK with the identifier P.PersonID. To get the value of this count, we can use a subquery: the aggregation function <strong>COUNT(*)</strong> lets us count all the tuples present in Residence. It does this after filtering them with the condition that their foreign key PersonFK references the person being processed in the Person table.</p>
<p>It’s important to note that the subquery will only return one value generated by COUNT(), and only one column generated by this function. This meets the requirement that every subquery used in the SELECT statement must fulfill.</p>
<p>Finally, it’s worth mentioning that this value generated in the subquery populates an additional column which we’ve added by including the subquery itself in the SELECT for each tuple of our query. In other words, each tuple will need a value for this <strong>new column</strong>, which they’ll get by executing the correlated subquery on that specific tuple.</p>
<p>SELECT and FROM aren’t the only statements where subqueries are allowed. We can also use them in a WHERE, HAVING, or even ORDER BY clause. More importantly, a query can have an arbitrary number of subqueries (nested or not) depending on its needs.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.PoolID,
    P.Name <span class="hljs-keyword">AS</span> PoolName,
    C.Name <span class="hljs-keyword">AS</span> CityName,
    P.Status,
    (
        <span class="hljs-keyword">SELECT</span> PoolID
        <span class="hljs-keyword">FROM</span> CityPool C
        <span class="hljs-keyword">WHERE</span> C.PoolID = P.PoolID
    ) <span class="hljs-keyword">AS</span> CityPoolID
<span class="hljs-keyword">FROM</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> Pool
        <span class="hljs-keyword">WHERE</span> Status = <span class="hljs-string">'maintenance'</span>
    ) <span class="hljs-keyword">AS</span> P
    <span class="hljs-keyword">JOIN</span> City C <span class="hljs-keyword">ON</span> P.CityFK = C.CityID;
</code></pre>
<p>For example, in a query like the one above, we can see that there is not only a subquery in the SELECT but also one in the FROM.</p>
<p>In this specific case, the query gets information about all the pools currently under maintenance, including details about the city the pools are located in (such as its name). There’s also an additional column indicating the pool's identifier if it’s of the CityPool type, leaving it blank if it’s not.</p>
<p>So to resolve this query, we first need to get information about the pools under maintenance. This simply involves going through the tuples in the Pool table and selecting those whose Status value is <strong>‘maintenance’</strong>.</p>
<p>Then, to gather information about the city where each pool is located (along with the Pool tuples we just obtained), we can use a JOIN that operates on the previous tuples and the City table. This is why we’re extracting all Pool tuples using a subquery.</p>
<p>So although the type of JOIN is not explicitly specified, by using the ON clause SQL automatically interprets it as an INNER JOIN (it would also be interpreted as INNER type if we had used the USING clause). But this practice is not recommended, as in most situations where the JOIN type is omitted, the readability of the code is compromised, especially when there are many JOINs in the same query.</p>
<p>Here, in the ON clause, the JOIN condition states that in the same tuple of the Cartesian product, the foreign key CityFK – which represents the city where the pool is located – must have the same value as the CityID identifier of the city in the tuple.</p>
<p>Then, to attach the extra column with the pool identifier from CityPool for those tuples that represent pools of that type, respectively, we’ll use a subquery. This subquery searches the CityPool table for a tuple whose PoolID matches the PoolID from Pool. This checks if the pool from Pool is actually of the CityPool type or not.</p>
<p>In this way, the subquery will return the <strong>identifier value</strong> if it’s of the <strong>CityPool type</strong> – otherwise, it will return <strong>nothing</strong>, meaning it will return a <strong>table without tuples</strong> (or in other words, an empty set or <strong>multiset</strong>, rather).</p>
<p>This is allowed in SQL, but it can sometimes cause errors, so it's generally not a good practice to use subqueries in the SELECT that aren’t guaranteed to return at least some tuple.</p>
<p>So for those pools that aren’t of the CityPool type, the subquery will return nothing. This means that the value of the extra column in the SELECT will be NULL as we can see when executing the query.</p>
<p>Since it doesn’t return any tuple with any value, we’ll insert an <strong>unknown</strong> value. The way to represent this in SQL is with the special value NULL. Also, this extra column by default has no name, so we can assign it a recognizable alias using the AS clause as shown in the query.</p>
<p>On the other hand, if we want to avoid having NULL values in the additional column, we can have this column contain boolean values where TRUE indicates that the pool is of the CityPool type and FALSE that it’s not.</p>
<p>Starting from the same query as before, the only change we need to make to achieve this is to add an <strong>IS NOT NULL</strong> check. For each tuple, it checks whether the value inserted in the additional <strong>CityPoolType</strong> column is NULL or not. Thus, if its type is indeed CityPool, the value in the additional column provided by the original subquery won’t be NULL. This meets the IS NOT NULL condition and returns TRUE. Conversely, if it’s not of that type, IS NOT NULL won’t be met, and the additional column in this case will be filled with FALSE.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.PoolID,
    P.Name <span class="hljs-keyword">AS</span> PoolName,
    C.Name <span class="hljs-keyword">AS</span> CityName,
    P.Status,
    (
        <span class="hljs-keyword">SELECT</span> PoolID
        <span class="hljs-keyword">FROM</span> CityPool C
        <span class="hljs-keyword">WHERE</span> C.PoolID = P.PoolID
    ) <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">NULL</span> <span class="hljs-keyword">AS</span> CityPoolType
<span class="hljs-keyword">FROM</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> Pool
        <span class="hljs-keyword">WHERE</span> Status = <span class="hljs-string">'maintenance'</span>
    ) <span class="hljs-keyword">AS</span> P
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> City C <span class="hljs-keyword">ON</span> P.CityFK = C.CityID;
</code></pre>
<p>Here, we need to be careful about where we place the IS NOT NULL condition. On one hand, we might think of comparing the PoolID attribute of the CityPool table itself in the SELECT clause of the subquery. If we do this, we’ll be comparing a value that may or may not exist with NULL, so the final result of the subquery will be FALSE if the pool is of the CityPool type.</p>
<p>But if it’s of another type, there won't even be a value for that PoolID attribute in the CityPool table, so the comparison with NULL won’t be executed. This will result in the final query output having the additional column contain NULL values for pools that aren’t of the CityPool type and FALSE for those that are of the corresponding type.</p>
<p>This happens because we shouldn’t compare PoolID with NULL, as its value may or may not exist. And if it doesn't exist, the check won't be executed for all the tuples in our query.</p>
<p>Instead, we should perform this check on the result of the entire subquery. It can be NULL when the pool is not of type CityPool – and so we see values in the additional column filled with NULL in the final result. Or it can contain a valid identifier different from NULL, which violates the IS NOT NULL condition.</p>
<p>In short, the check to ensure that the additional column is of <strong>boolean</strong> type should compare the result of the entire subquery (which is either NULL or a specific value) with the NULL value itself. This checks to see if each tuple in our resulting table matches or not.</p>
<p>In summary, although it's not good practice to use subqueries in the SELECT clause that may result in an <strong>empty set</strong>, we can do so long as it doesn't make the readability or efficiency of the query worse. We also need to have certain guarantees that it does what it’s expected to do.</p>
<p>So far, we've performed membership checks with IN, as well as checks with other operators. We’ve used individual attributes to verify if the value of a certain attribute was in a set formed by the values of an attribute, among other conditions. And sometimes we need these conditions to involve more than one attribute for verification.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> E.EntryTimestamp, E.PersonFK, E.PoolFK
<span class="hljs-keyword">FROM</span> Entry E
<span class="hljs-keyword">WHERE</span> (E.EntryTimestamp, E.PersonFK, E.PoolFK) <span class="hljs-keyword">IN</span> (
        <span class="hljs-keyword">SELECT</span> PS.EntryFK, PS.PersonFK, PS.PoolFK
        <span class="hljs-keyword">FROM</span> PoolSanction PS
    );
</code></pre>
<p>For example, above we have a query that retrieves all the tuples from Entry that have been sanctioned with some pool sanction from the PoolSanction table. To do this, we simply need to go through the tuples in Entry and, for each one, check if it has a sanction. In other words, we verify if there is a tuple in PoolSanction whose foreign key to Entry references the tuple we’re examining.</p>
<p>When doing this, the first thing we notice is that the primary key of Entry doesn’t consist of a single attribute, but rather 3. This is just like the foreign key in PoolSanction – it determines that the entry that has been sanctioned doesn’t have one attribute, but three.</p>
<p>So under normal conditions, we could use a subquery to get all the foreign key values from PoolSanction, then check if the identifier (primary key) of each entry belongs to that set of values using the IN operator. But here we can’t do it the same way because we need to work with three attributes instead of one.</p>
<p>That's why, in the subquery, instead of returning a single attribute, we return all those that make up the foreign key to Entry (these are <strong>(EntryFK, PersonFK, PoolFK)</strong>). With this, we have a set of tuples where each one refers to a tuple in Entry that has been sanctioned.</p>
<p>Specifically, each of these tuples in the set refers to the three attributes that make up the primary key of Entry, which are <strong>(EntryTimestamp, PersonFK, PoolFK)</strong>. So to check if an entry belongs to this set, we simply go through it, looking to see if any of the tuples match exactly with the tuple of the entry's primary key (with all three attributes having equal values).</p>
<p>We do this using the IN operator, where instead of specifying a single attribute, we can specify an arbitrary number of them in parentheses. Thus, the IN operator will perform the same operation as in previous cases, taking the primary key <strong>(EntryTimestamp, PersonFK, PoolFK)</strong> of each entry and comparing it with each of the tuples from the subquery, attribute by attribute. If any of them match, then it belongs to the set, fulfilling the condition.</p>
<p>Here, it's very important to note that the tuples compared by IN must be the same size. This means that they need to have the same number of attributes, the same data type (or at least be comparable), and their semantics must be the same. That is, if for each tuple in Entry we use <strong>(EntryTimestamp, PersonFK, PoolFK)</strong> to check if that three-attribute tuple is in the subquery set, then that subquery must contain tuples of three attributes where:</p>
<ul>
<li><p>the first one is <strong>EntryFK</strong>, which refers to the <strong>EntryTimestamp</strong> attribute of the primary key of Entry,</p>
</li>
<li><p>The second one is <strong>PersonFK</strong>, referring to <strong>PersonFK</strong> of the primary key,</p>
</li>
</ul>
<p>and so on. This ensures that the comparison is semantically correct, even though in the DDL the primary key might have been defined in a completely different order.</p>
<p>Another variation of this query is to list all the sanctioned entries along with the information of the person who has the entry.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.*, E.EntryTimestamp, E.PersonFK, E.PoolFK
<span class="hljs-keyword">FROM</span> Person P <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Entry E <span class="hljs-keyword">ON</span> P.PersonID=E.PersonFK
<span class="hljs-keyword">WHERE</span> (E.EntryTimestamp, E.PersonFK, E.PoolFK) <span class="hljs-keyword">IN</span> (
        <span class="hljs-keyword">SELECT</span> PS.EntryFK, PS.PersonFK, PS.PoolFK
        <span class="hljs-keyword">FROM</span> PoolSanction PS
    );
</code></pre>
<p>For this, based on the previous solution where we got the list of sanctioned entries, the only additional step we need to take is to perform a JOIN between Entry and Person. In doing this, we only keep those tuples from the Cartesian product where the foreign key PersonFK from Entry refers to the primary key {PersonID} from the information coming from Person.</p>
<p>We can also see that the condition checking whether the entry is sanctioned or not is the same. With this example, we can more clearly see the purpose of the JOIN operation, which is to gather information from multiple tables. So for each sanctioned entry we had before, if we now need to concatenate the information of the person to whom the foreign key PersonFK points, we can simply perform the Cartesian product between both tables and impose a condition to ensure that the reference of PersonFK is indeed the person present in the tuple.</p>
<p>Continuing with the uses of this last technique, where we use operators like IN to check if a certain combination of attribute values belongs to a set of tuples, in the following example we have a query that lists all the trips from the Voyage table for which there is a return trip. That is, we need to find all trips going from city A to city B for which there is at least one other different trip going from B to A.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Voyage V
<span class="hljs-keyword">WHERE</span> (V.DepartureCityFK, V.ArrivalCityFK) <span class="hljs-keyword">IN</span> (
        <span class="hljs-keyword">SELECT</span> V2.ArrivalCityFK,
            V2.DepartureCityFK
        <span class="hljs-keyword">FROM</span> Voyage V2
    )
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> (V.DepartureCityFK, V.ArrivalCityFK);
</code></pre>
<p>To do this, the first thing we need to realize is that the primary key of Voyage includes the attributes <strong>DepartureCityFK</strong> and <strong>ArrivalCityFK</strong>, which refer to the start and end cities of the trip, respectively. So if we have multiple trips with different values in these attributes, we’ll definitely know that both trips are different. This is because even if the rest of the primary key attributes were the same, as long as at least one of them is different, the trips must necessarily be different.</p>
<p>So we can formulate the query similarly to the previous ones, going through all the tuples in Voyage and for each one, checking if there is a trip whose start and end cities are the same the end and start cities of the trip being checked. So for each trip in Voyage, we construct a correlated subquery where we again go through all the tuples in Voyage and only get the values of the DepartureCityFK and ArrivalCityFK attributes. Then, we check if the values of these attributes from the trip in the "higher level" query are in the set of tuples we just built.</p>
<p>But in this case, if we look at the code, the order of the attributes is swapped compared to the order of those same attributes in the subquery. What we really want to check is that the value of the DepartureCityFK attribute of the tuple we are checking in the query matches the value of the ArrivalCityFK attribute of some tuple in the subquery. Also, we need to check that the value of the ArrivalCityFK attribute of the query's tuple matches the value of the DepartureCityFK attribute of the same tuple that matched the previous pair of attributes.</p>
<p>We can more easily understand this by viewing the pair <strong>(V.DepartureCityFK, V.ArrivalCityFK)</strong> as if they were the start and end cities, A and B, of a trip. What we want to check is if there is any tuple in the subquery that has B and A as the start and end cities, respectively.</p>
<p>The simplest way to make this check is either to reverse the order of the attributes in the tuple <strong>(V.DepartureCityFK, V.ArrivalCityFK)</strong> or in the attributes of the SELECT in the subquery. This is what we’ve decided to do here, which is why ArrivalCityFK is returned before DepartureCityFK.</p>
<p>Finally, to more easily check for the existence of these round trips, we can add the ORDER BY clause, which orders by multiple attributes instead of just one. That is, we use the attributes <strong>(V.DepartureCityFK, V.ArrivalCityFK)</strong> as the sorting criteria. SQL orders by the pairs of values for each tuple, as if each possible pair of values were considered a single value that could be compared with others.</p>
<p>By doing this, we can easily focus on the departure city of a trip and then look for another trip whose arrival city has the same value. Then we can find one whose departure city matches the arrival city of the original trip, thus finding a pair of trips that form a round trip to a city.</p>
<p>Finally, let’s look at another query where we need to compare values of multiple attributes at once. Here, all trips are listed whose associated cruise (the one making the trip) has been assigned to its cruise line on the same start date of the trip.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> V.*
<span class="hljs-keyword">FROM</span> Voyage V
<span class="hljs-keyword">WHERE</span> (V.ShipFK, V.DepartureDate)
  <span class="hljs-keyword">IN</span> (
    <span class="hljs-keyword">SELECT</span> SA.ShipFK, SA.StartDate
    <span class="hljs-keyword">FROM</span> ShipAssignment SA
  );
</code></pre>
<p>To implement this, we need to consider all the attributes that <strong>Voyage</strong> has, including the information contained in the foreign keys, to avoid having to perform unnecessary operations like a JOIN with the <strong>CruiseShip</strong> or <strong>CruiseLine</strong> table.</p>
<p>In this case, we structure the query similarly, first going through all the tuples of Voyage and checking if the cruise has been assigned to its cruise line on the same date as the start of the trip.</p>
<p>To make this check easier, we construct a subquery that returns all the values of the <strong>ShipFK</strong> and <strong>StartDate</strong> attributes from the <strong>ShipAssignment</strong> table. This way, later in our query we can check if the cruise making the trip (which is referenced with the foreign key ShipFK of Voyage) was assigned on the DepartureDate of the Voyage tuple (start date of the trip) to any cruise line.</p>
<p>As you can see, we can simplify the query if we think of it as getting all trips for a cruise ship that has been assigned a start date with any cruise line. In other words, it doesn't have to be a specific line, but any line to which it was assigned on the date indicated by <strong>DepartureDate</strong> of <strong>Voyage</strong>. So in the WHERE clause, it checks if the pair of values taken by the attributes <strong>(V.ShipFK, V.DepartureDate)</strong> are found in the subquery. And this time it maintains the correct order of the attributes, since ShipFK of Voyage must match ShipFK of ShipAssignment, and <strong>DepartureDate</strong> of <strong>Voyage</strong> must match StartDate of ShipAssignment, respectively.</p>
<p>On one hand, the match of ShipFK ensures that the cruise ship making the trip is the same as the one assigned in the ShipAssignment tuple. Likewise, the match of the date attributes ensures that this assignment was made on the start date of the trip.</p>
<p>We have also solved this query using a correlated subquery and the IN operator, although it's not the only way. As you can guess, there's always the option to use JOIN operations and conditions to filter the tuples, which can be more or less efficient in certain cases. This is why it's important to understand what SQL does under the hood, like whether it actually builds and stores all the tuples of a subquery or Cartesian product in memory, and when it does so.</p>
<h3 id="heading-common-table-expressions">Common Table Expressions</h3>
<p>We have seen that subqueries allow us to use the result of one query within another query. We can construct this once during the execution of the entire query if it’s not correlated, or once for each tuple of the table with which it’s correlated. In other words, we can see a subquery as a set of tuples that we operate with in a query.</p>
<p>But we don't always need queries to be correlated. We’ve seen that some queries can be resolved by non-correlated queries, meaning sets of tuples that are constructed only once and are sufficient to resolve the entire query in which they are contained.</p>
<p>In these situations, to simplify notation, we can use a tool called <strong>CTE (Common Table Expression)</strong> in SQL. These typically use the <a target="_blank" href="https://www.geeksforgeeks.org/sql/sql-with-clause/"><strong>WITH</strong></a> <strong>clause</strong>. With this, we can define and store the result of a subquery in a temporary table that needs an alias. So instead of using a subquery in the construction of a query, we define a <a target="_blank" href="https://stackoverflow.com/questions/49990666/trying-to-create-multiple-temporary-tables-in-a-single-query"><strong>temporary intermediate table</strong></a> <strong>(Common Table Expression)</strong> that only exists during the execution of the query and contains all the tuples generated by a certain subquery. Again, we need to use an alias to refer to it, just as we have to provide tables with a name and a schema when we create them in the DDL.</p>
<p>To understand the WITH clause with an example, we can consider the query that gets information about all currently active cruises. Here, active means assigned to a cruise line at the current date when the query is executed.</p>
<p>Before writing code, it's helpful to think about how the query will be structured, meaning where we’ll get the data to respond, how we should combine the different tables with that data, what conditions or operations need to be applied to them or the tuples resulting from the operations performed, and so on.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> ActiveShips <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> ShipFK
    <span class="hljs-keyword">FROM</span> ShipAssignment
    <span class="hljs-keyword">WHERE</span> StartDate &lt;= <span class="hljs-built_in">CURRENT_DATE</span>
        <span class="hljs-keyword">AND</span> EndDate &gt;= <span class="hljs-built_in">CURRENT_DATE</span>
)
<span class="hljs-keyword">SELECT</span> CS.ShipID, CS.Speed, CS.PassengerCapacity
<span class="hljs-keyword">FROM</span> ActiveShips A <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> CruiseShip CS <span class="hljs-keyword">ON</span> CS.ShipID = A.ShipFK;
</code></pre>
<p>In this case, the information for all cruise assignments, whether current or not, is in the ShipAssignment table. So, to know which cruises are currently assigned to a cruise line, we can take advantage of the fact that this table has a <strong>foreign key ShipFK</strong> that identifies the assigned cruise in each tuple of <strong>ShipAssignment</strong>.</p>
<p>So, if we set the condition that the StartDate of the assignment should be before the current date gotten from <strong>CURRENT_DATE</strong>, and that the EndDate is after the current date, we’ll get all those assignments that are valid on the current date. By extracting the values taken by the foreign key ShipFK for those assignments, we can identify the cruises that are currently assigned.</p>
<p>But the query not only asks us to <strong>identify them</strong> – but also to get <strong>information about them</strong> stored in CruiseShip. So, we save the identifiers of the cruises we got earlier in a temporary table to use in the query. In other words, we could make the conditions on StartDate and EndDate apply to ShipAssignment in a subquery. But to simplify the notation and demonstrate how to use <strong>CTEs</strong>, we’ll use the WITH clause where we define all the subquery code and assign an alias to that temporary table (see above code).</p>
<p>Specifically, by doing this, we’ll be saving the identifiers of the currently active cruises in the temporary table named ActiveShips. This is the alias we assigned using the AS operator – but it works in reverse in the WITH clause: first, you write the alias name and then you writethe code that gets the data from the intermediate table (the element to which the alias name is assigned).</p>
<p>So, when we use the WITH statement, we see that we have constructed an ActiveShips table with the result of what could be a <strong>non-correlated subquery</strong> – but for simplicity, we’ve refactored it so that its result is stored in an intermediate table with a certain alias.</p>
<p>Now, we can treat ActiveShips as if it were another table in the database, performing a JOIN between it and CruiseShip to get all the information about the active cruises. We impose an equality condition on the <strong>ShipFK</strong> and <strong>ShipID</strong> attributes of the <strong>ActiveShips</strong> and <strong>CruiseShip</strong> tables, respectively. This means we only keep those tuples from the Cartesian product where the foreign key ShipFK refers to the ShipID identifier of that same tuple. This allows us to find the complete information about a specific cruise.</p>
<p>In the previous query, we could have easily skipped using WITH and made ActiveShips a subquery to which we could’ve also assigned an alias. But when using a subquery, even if we assign it an alias, we can’t use it in just any part of the query. That is, if we have a subquery in a FROM or a SELECT, we can’t use it in other parts of the query in the same way as we can use an intermediate table defined in a WITH. This (WITH) we can reference at any point in the query, regardless of whether it’s formed by more subqueries.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> VoyageDistance <span class="hljs-keyword">AS</span> (
  <span class="hljs-keyword">SELECT</span> * 
  <span class="hljs-keyword">FROM</span> Voyage
  <span class="hljs-keyword">WHERE</span> Distance &gt; <span class="hljs-number">1000</span>
)
<span class="hljs-keyword">SELECT</span> DepartureDate, ArrivalDate, Distance
<span class="hljs-keyword">FROM</span> VoyageDistance 
<span class="hljs-keyword">WHERE</span> DepartureDate <span class="hljs-keyword">BETWEEN</span> <span class="hljs-string">'2025-01-01'</span> <span class="hljs-keyword">AND</span> <span class="hljs-string">'2025-06-30'</span>;
</code></pre>
<p>We have another similar example in the query above. Here, we consider a query that gets information about all voyages that started in the first half of 2025 (approximately) and have a distance greater than 1000 kilometers. The approach in this case is simpler since all the information we need is found in the <strong>Voyage</strong> table. So the condition that the distance is greater than 1000 kilometers is easily modeled with a <strong>WHERE</strong> clause and the expression <strong>Distance &gt; 1000</strong>.</p>
<p>Just like before, in this query we could also skip using WITH and include both the distance and the condition on the start date of the voyage in a single WHERE. But often we might need to modify or expand a query – for example, in the future we might be asked for a query based on this one, but with more or fewer conditions. So if we conducted an <strong>analysis</strong> of our domain, user requirements, and the query code, we might conclude that tuples with voyages over 1000 kilometers could be needed in multiple parts of the same query.</p>
<p>In this example, this phenomenon might not occur, but it illustrates that in a real situation, we may need to consider various factors that affect query design.</p>
<p>So, say we assume that the Voyage tuples with <strong>Distance&gt;1000</strong> could potentially be used multiple times in a single query across multiple statements (in future modifications of this query). Then the most maintainable option is to use a WITH clause where we temporarily store these tuples and then use them in the query through the alias of this intermediate table (as if it were a regular database table). Then, we can add another WHERE clause at the very end of the query, declaring the condition that the start date of the voyage is in the first half of 2025. We can model this with the <strong>BETWEEN</strong> operator, the <strong>EXTRACT()</strong> function, or many other ways.</p>
<p>Finally, it’s worth noting that using the WITH clause without a clear reason isn’t considered a good practice. (Examples of such a clear reason might include a design decision based on user requirements or a thorough analysis of the query that concludes that it might be useful to have an intermediate table like VoyageDistance in the future).</p>
<p>This is mainly because, in situations like this, a WHERE clause is being used both in the construction of the intermediate table and in the resulting table from the query. This means multiple filters might be applied internally, which can be inefficient.</p>
<p>But the DBMS often automatically applies certain techniques like <a target="_blank" href="https://dba.stackexchange.com/questions/212198/how-can-i-find-out-if-a-sql-function-can-be-inlined"><strong>inlining</strong></a> to optimize query execution through <strong>refactorizations</strong> of the <strong>execution plan</strong>. In other words, even if our code is not the most optimal, the DBMS can automatically find an equivalent and more optimal way to resolve the query.</p>
<p>To illustrate that the intermediate tables we define in the WITH clause can be constructed with subqueries as "complex" as we want, consider this query:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> Pending <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> D.*
    <span class="hljs-keyword">FROM</span> DrivingLicenseRequest D
        <span class="hljs-keyword">LEFT JOIN</span> DrivingLicense A <span class="hljs-keyword">USING</span> (LicenseID)
        <span class="hljs-keyword">LEFT JOIN</span> RejectedDrivingLicense R <span class="hljs-keyword">USING</span> (LicenseID)
    <span class="hljs-keyword">WHERE</span> A.LicenseID <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
        <span class="hljs-keyword">AND</span> R.LicenseID <span class="hljs-keyword">IS</span> <span class="hljs-keyword">NULL</span>
)
<span class="hljs-keyword">SELECT</span> P.Name, Pending.*
<span class="hljs-keyword">FROM</span> Pending <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P <span class="hljs-keyword">ON</span> P.PersonID = Pending.PersonFK;
</code></pre>
<p>We’re getting information on all driving license requests currently being processed, meaning those that have not yet been accepted or rejected. We’re also including information about the person who made each request.</p>
<p>In this case, the key point is to realize that the requests in process are represented by tuples in DrivingLicenseRequest that aren’t referenced by any tuple in either DrivingLicense or <strong>RejectedDrivingLicense</strong> (since they aren’t yet accepted or rejected).</p>
<p>In this case, we can use LEFT JOIN so that by combining all these tables with LEFT JOIN operations, we can gather complete information about the requests. This means constructing a table formed by all the attributes of the three tables in the hierarchy, where some of them will be NULL or not in each tuple, depending on whether they represent accepted, rejected, or pending requests.</p>
<p>Specifically, since the foreign keys of the inheriting entities in the hierarchy are both called LicenseID (matching the identifier <strong>{LicenseID}</strong> of the superclass), the <strong>LEFT OUTER JOINs</strong> are performed by applying an equality condition on this attribute. This ensures that the tuples we get contain information about the same request, rather than multiple requests in the same tuple of the Cartesian product.</p>
<p>We use LEFT JOIN because the first table we combine is <strong>DrivingLicenseRequest</strong>. We know all its tuples are non-null because it represents the superclass of the hierarchy and contains information on all requests in the database, regardless of their status. So by placing this table on the left of the JOIN operation, we ensure that the information of all the tuples it contains appears – and it fills in NULL for the attributes from the other table, DrivingLicense.</p>
<p>Then, we do another LEFT JOIN with RejectedDrivingLicense following the same process. This results in a table where, despite using USING in the JOIN operations, we can impose conditions on the LicenseID attributes of all the tables. So for a tuple of the resulting Cartesian product to represent a pending request, the LicenseID attributes of the <strong>DrivingLicense</strong> and RejectedDrivingLicense tables must be NULL. This indicates that there are no tuples in the respective tables because the LEFT JOIN has been filled in with NULL if they didn't exist. We declare this condition using a WHERE clause and the IS operator, as you can’t compare an attribute with NULL directly using the = operator.</p>
<p>At this point, to simplify the query syntax and avoid chaining too many JOINs, we can create an intermediate table with the result we got by performing these LEFT JOINs and applying the previous condition. This way, we can later perform an INNER JOIN in the query to get the information of the person who made the request. We do this all through the <strong>PersonID</strong> attribute of the <strong>Person</strong> table and the <strong>foreign key PersonFK</strong> of the intermediate table Pending, which comes from the DrivingLicenseRequest table and refers to the person associated with the request.</p>
<p>In this query, we could also consider combining all the joins in a single FROM clause and skipping the WITH. This would be correct, but it would complicate the code by having all the JOINs chained. And, although this strategy can be more efficient under certain circumstances, we should seek a balance between code readability and efficiency.</p>
<p>To illustrate that the intermediate tables in the WITH clause can be defined by queries that contain subqueries, we’ll consider the same query as before and try to solve it using a different approach.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> Pending <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> D.*
    <span class="hljs-keyword">FROM</span> DrivingLicenseRequest D
    <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
            <span class="hljs-keyword">SELECT</span> *
            <span class="hljs-keyword">FROM</span> DrivingLicense A
            <span class="hljs-keyword">WHERE</span> A.LicenseID = D.LicenseID
        )
        <span class="hljs-keyword">AND</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
            <span class="hljs-keyword">SELECT</span> *
            <span class="hljs-keyword">FROM</span> RejectedDrivingLicense R
            <span class="hljs-keyword">WHERE</span> R.LicenseID = D.LicenseID
        )
)
<span class="hljs-keyword">SELECT</span> P.Name, Pending.*
<span class="hljs-keyword">FROM</span> Pending <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P <span class="hljs-keyword">ON</span> P.PersonID = Pending.PersonFK;
</code></pre>
<p>To get pending requests, keep the tuples in DrivingLicenseRequest whose primary key {<strong>LicenseID</strong>} is not referenced (via the foreign key <strong>LicenseID</strong>) by any tuple in DrivingLicense or RejectedDrivingLicense.</p>
<p>The simplest option to implement this is to go through all the tuples in DrivingLicenseRequest using the FROM clause, and for each of them, construct two very similar correlated queries.</p>
<ul>
<li><p>We can have one that gets all the tuples from DrivingLicense whose foreign key LicenseID refers to the primary key LicenseID of the tuple in DrivingLicenseRequest that we are going through, and</p>
</li>
<li><p>We can have another subquery that does the same but gets tuples from the RejectedDrivingLicense table.</p>
</li>
</ul>
<p>In this way, we can later check if any of the tables returned by the subqueries contain tuples or not using the EXISTS operator.</p>
<p>If any of the subqueries return tuples, then the request is either accepted or rejected. But if both subqueries return an empty set, it means that for a certain request in DrivingLicenseRequest**,** there is no tuple in the respective DrivingLicense or RejectedDrivingLicense tables that references it. This then indicates that the request is being processed.</p>
<p>With this process, we get the pending requests, which we store in an intermediate table using the WITH clause. To combine the information of the person who made each request, we use the intermediate table in the query, specifically in an INNER JOIN operation with the Person table, just as we did before.</p>
<p>So with this example, we’ve seen that there are multiple SQL constructions that lead to the same result – meaning a query doesn't necessarily have to be solved in just one way.</p>
<p>Also, by using the WITH clause, we can define each intermediate table with SQL code that’s as <strong>"complex"</strong> as we need it to be. We can include subqueries, conditions, and generally any SQL statement, except for a WITH, which by default can’t appear inside another WITH.</p>
<p>If we need to use an intermediate table to solve a query defined as a <strong>CTE</strong>, we need to define it at the same level as the other intermediate tables in our query, meaning in a single WITH statement (as we’ll see below).</p>
<p>So far, we have seen that we can use the WITH statement to define an intermediate table that we use to solve the query more comfortably and easily in certain situations. But, we might need several intermediate tables to solve a query, not just one.</p>
<p>For example, in the below code we have a query that gets information about people who have lived in at least two cities. We solved this query in the <strong>“Tuple filtering”</strong> section using JOIN operations – but we can also follow a similar approach where we first create several different intermediate tables and finally solve the query based on the results of these intermediate tables.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> R1 <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> PersonFK, CityFK <span class="hljs-keyword">AS</span> CityA
    <span class="hljs-keyword">FROM</span> Residence
),
R2 <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> PersonFK, CityFK <span class="hljs-keyword">AS</span> CityB
    <span class="hljs-keyword">FROM</span> Residence
),
CityPairs <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">DISTINCT</span> R1.PersonFK
    <span class="hljs-keyword">FROM</span> R1 <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> R2 <span class="hljs-keyword">ON</span> (R1.PersonFK = R2.PersonFK
        <span class="hljs-keyword">AND</span> R1.CityA &lt;&gt; R2.CityB)
)
<span class="hljs-keyword">SELECT</span> P.*
<span class="hljs-keyword">FROM</span> CityPairs MC <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P <span class="hljs-keyword">ON</span> MC.PersonFK = P.PersonID
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> P.PersonID;
</code></pre>
<p>First, we can create several intermediate tables that contain all the tuples from Residence – specifically the information about the person and city that make up each residence. We can do this by obtaining the attributes PersonFK and CityFK, which are foreign keys that refer to the person who has lived in a certain city during that residence. By constructing several intermediate tables with this information, we can rename CityFK with an alias like CityA in one of them and CityB in the other intermediate table, so that later the JOIN between them has a clearer syntax.</p>
<p>To construct several intermediate tables in a single WITH statement, we can chain them with commas. Instead of using the WITH keyword multiple times, we have to use it only once and chain all the intermediate tables we want with commas, as shown above.</p>
<p>Subsequently, with the intermediate tables R1 and R2 containing this information, we can create another intermediate table where we get the identifiers of all the people who have had a residence in several different cities (or in at least two cities).</p>
<p>To do this, we can perform an INNER JOIN between R1 and R2 (a Cartesian product of their tuples) and keep the tuples from the Cartesian product where the foreign key values PersonFK match and the CityFK values do not match. This way, we keep those tuples from the Cartesian product that represent information about several residences of the same person in different cities.</p>
<p>These identifiers are for the people whose information we need to get from the Person table. So now we can finally perform an INNER JOIN between the intermediate table CityPairs and Person, so that the final result of the query is the information of the people who have had at least two residences in different cities. (They would not have appeared in a tuple of the Cartesian product between R1 and R2 otherwise.)</p>
<p>The important point about this query is to note that we have used <strong>multiple intermediate tables</strong> in the same WITH clause to solve it – and this is entirely <strong>possible</strong> but not always recommended. We can resolve this query in various ways, each with its own advantages or disadvantages depending on the characteristics we need the code to have, such as clarity, efficiency, maintainability, and so on.</p>
<p>To conclude this CTE section, let's consider another query where we need to get information about bus trips that have taken place after 2025 and where the bus has WiFi. The simplest way to create this query would be to gather information from the CityBus and BusTrip tables using a JOIN, and then apply conditions on the tuples of the corresponding Cartesian product. But to illustrate using multiple <strong>intermediate tables (CTEs)</strong> in a single <strong>WITH</strong> clause, in this case, we’ll divide the query resolution into several parts.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> WifiBuses <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> Plate, RouteNumber
    <span class="hljs-keyword">FROM</span> CityBus
    <span class="hljs-keyword">WHERE</span> FreeWifi = <span class="hljs-keyword">TRUE</span>
),
AvailableTrips <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> TripDate, StartAddress, EndAddress, PlateFK
    <span class="hljs-keyword">FROM</span> BusTrip
    <span class="hljs-keyword">WHERE</span> EXTRACT(<span class="hljs-type">YEAR</span> <span class="hljs-keyword">FROM</span> TripDate) &gt;= <span class="hljs-number">2025</span> 
)
<span class="hljs-keyword">SELECT</span> T.TripDate, T.StartAddress, T.EndAddress, B.RouteNumber
<span class="hljs-keyword">FROM</span> AvailableTrips T <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> WifiBuses B <span class="hljs-keyword">ON</span> B.Plate = T.PlateFK;
</code></pre>
<p>First, we’ll get information about buses with WiFi in an intermediate table. To construct this table, we simply apply the condition FreeWifi=TRUE on the tuples of the CityBus table. In this case, when we do a <strong>SELECT * FROM CityBus;</strong> we can see that in the FreeWifi attribute, the boolean values are represented with the letters <strong>‘t’</strong> or <strong>‘f’</strong> – so we might think that in the query we should compare the attribute with <strong>‘t’</strong>.</p>
<p>But boolean values in SQL are TRUE and FALSE, even though the DBMS <a target="_blank" href="https://dba.stackexchange.com/questions/115234/why-t-and-f-instead-of-true-and-false"><strong>represents</strong></a> them with another type of notation. So the correct way to check if the attribute contains the logical value <strong>true</strong> is to compare it with <strong>TRUE</strong>. Even though the representation of the boolean value might change, in SQL we should always operate with boolean values using the literals <strong>TRUE</strong> and <strong>FALSE</strong>.</p>
<p>Second, we construct another intermediate table with information about bus trips that have occurred in 2025 or later. We do this by getting all the tuples from BusTrip and filtering them using the <strong>EXTRACT()</strong> function and the <strong>YEAR</strong> feature of the date.</p>
<p>Finally, in the query, we perform a JOIN between both intermediate tables to gather all the information about trips and buses. This way, we get tuples with trips that occurred on dates equal to or after the year 2025, along with the information about the bus with WiFi that made that trip.</p>
<p>But in this case, we only return the route number of the bus to the user, which is also part of the information in the CityBus table. If this isn’t enough to identify the bus, we could also return its license plate in the SELECT, for example. This decision depends on what the end user needs.</p>
<p>Also, with this query, we can more clearly see the effect of coding a query using multiple intermediate tables on how efficiently it executes. For example, if we coded the query without WITH (and instead with JOIN operations between the respective CityBus and BusTrip tables and imposed conditions on the resulting tuples), we have to consider that the entire Cartesian product would be performed first and then filtered by the conditions.</p>
<p>But by using intermediate tables where each one imposes a certain condition on the tuples of each table, we can reduce the number of tuples in each intermediate table, since <strong>WifiBuses</strong> won’t contain all existing buses, but only those with WiFi (which will be fewer).</p>
<p>By applying this technique (known as <a target="_blank" href="https://docs.oracle.com/cloud/latest/big-data-discovery-cloud/BDDEQ/ceql_bp_filter_early.htm#BDDEQ-concept_F3B83B6965AC40429E5C68AB330BA74E">early filtering</a>), we ensure that when performing the final JOIN between the intermediate tables, the Cartesian product results in <strong>fewer tuples</strong> – meaning it works with smaller tables and is therefore <strong>more efficient</strong>.</p>
<p>Just keep in mind that in modern DBMS, this optimization can be carried out <a target="_blank" href="https://stackoverflow.com/questions/46727600/sql-performance-filter-first-or-join-first">automatically</a> even without using intermediate tables, depending on the nature of the query. So if it doesn’t significantly worsen the clarity of the query, we should filter the information from the tables to be combined via a JOIN as early as possible, which is why we have used multiple intermediate tables in a WITH clause.</p>
<h3 id="heading-set-operations">Set Operations</h3>
<p>We have seen that in most queries, we need to impose conditions on table tuples to filter them and keep only those that interest us. Sometimes, we even need to use logical operators to chain multiple conditions together.</p>
<p>But using logical operators AND, OR, and NOT is not the only way to chain multiple conditions. We can also take a different approach where, instead of applying a filter on all tuples, we divide the conditions that must be met and apply multiple filters, one for each condition based on logical operators. Finally, we get the resulting tuples from those filters and combine them using <strong>set theory operators</strong>, which perform functions equivalent to <strong>logical operators</strong>.</p>
<p>In other words, in SQL, we can chain multiple conditions in a WHERE clause, for example, using logical operators. Or we can use set theory operators to combine the resulting tuples from multiple filters, each applying one of those conditions, all without using logical operators.</p>
<p>As we will see below, the decision to use logical or set operators largely depends on the clarity of the resulting code and the efficiency we want to achieve in the query.</p>
<p>To start, let's consider a query where we need to get information on all pools that are currently in a maintenance or closed state. If we wanted to do this with what we already know, the simplest way would be to use a filter with a WHERE clause, combining the conditions that the Status attribute is 'closed' or 'maintenance' using the logical OR operator.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Pool
<span class="hljs-keyword">WHERE</span> Status=<span class="hljs-string">'maintenance'</span>
<span class="hljs-keyword">UNION</span>
<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> Pool
<span class="hljs-keyword">WHERE</span> Status=<span class="hljs-string">'closed'</span>;
</code></pre>
<p>Besides using this operator, we can rethink the query to solve it using set theory operators. In this case, using only one logical OR operator, we divide the WHERE condition into several conditions by removing that OR operator. This results in the conditions <strong>Status='maintenance'</strong> and <strong>Status='closed'</strong>, respectively.</p>
<p>Doing this, we can resolve two queries: one applying the first condition and another applying the second. This gives us two resulting tables, one with information about pools under maintenance and another table with all the closed pools.</p>
<p>But we wanted all of them in a single output table, not in several. So to combine all the tuples from both tables into one (so that they all appear in the resulting table), we use the UNION operator between both queries. It treats both queries as if they were <strong>multisets</strong> of tuples, resulting in another <strong>set</strong> of final tuples where the tuples from both tables are present. That is, all the tuples from both tables. This is just like in set theory where the union of sets <strong>AUB</strong> results in another set containing all the individuals from A, all from B, and all those in both A and B.</p>
<p>To apply a set theory operator, the schema of the tables returned by the queries we operate with has to be exactly the same. This means that they must have the same number of attributes with the same names and data types, and in the same order. Otherwise, we can’t compare tuples from both tables, and it wouldn’t be possible to determine if a tuple belongs to one of the sets involved in the operation.</p>
<p>When we run a query that includes a UNION, we can see that if there are duplicate tuples in the resulting tables from the queries we’re working with, those duplicate tuples disappear in the resulting table of the query. This happens because, by default, all set theory operators in SQL take multisets with tuples as input and produce a set of tuples, which means it won’t contain duplicate tuples. So if we want to force the appearance of duplicate tuples because the query requires it, we must add the <strong>ALL</strong> modifier after the corresponding <strong>UNION</strong>, <strong>INTERSECT</strong>, or <strong>EXCEPT</strong> operator.</p>
<p>For example, in this case, we want to get information about all the people who have rented at least one bike <strong>or</strong> owned at least one car in our system:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> PersonFK
<span class="hljs-keyword">FROM</span> Rental
<span class="hljs-keyword">UNION</span> <span class="hljs-keyword">ALL</span> 
<span class="hljs-keyword">SELECT</span> PersonFK
<span class="hljs-keyword">FROM</span> CarOwnership;
</code></pre>
<p>To do this, we first create a query that gets all the PersonID identifiers of people referenced by the tuples in the Rental table through their foreign key PersonFK. In other words, each tuple in Rental has a value in its foreign key PersonFK that corresponds to a certain person's identifier, which matches the value of their unique identifier PersonID. So selecting the PersonFK attribute is enough to get the identifiers of all the people who have at least one record in this table.</p>
<p>We do the same with another query on the CarOwnership table, which also has a foreign key PersonFK with the same characteristics.</p>
<p>Finally, when reviewing these partial results from the queries, we’ll see that some people may have rented several bikes or simply made several rentals, and they may also have multiple ownership records in CarOwnership, leading to duplicate tuples. So when building the final resulting table, we need to get the people who are present in one table or the other. This means we need to combine both tables with the UNION operator to get a final set with all the tuples from both tables.</p>
<p>In this specific case, we shouldn’t add the <strong>ALL modifier</strong>, as we simply want to know which people meet the condition of having at least one rental and at least one car ownership (so a person who has made multiple rentals doesn’t need to appear multiple times in the final table).</p>
<p>But if we wanted to keep the duplicate tuples, this example clearly shows that by adding ALL after the UNION operator, all duplicate tuples from both tables are preserved, resulting in the final table showing as many tuples with the same person's information as the number of rentals and properties they have had. In other words, the ALL modifier forces UNION to return a <strong>multiset</strong>, not a <strong>set</strong> that removes <strong>duplicate tuples</strong>.</p>
<p>We can see the effect of the ALL modifier at a glance by examining the resulting table from the query. But if we are working with a very large query or a database with a lot of information, we may want to <strong>wrap</strong> our query in another outer query that uses the aggregation function <strong>COUNT()</strong> to count how many tuples it returns.</p>
<p>For example, in the below code you can see that we have used the query we just looked at as a subquery in the FROM clause, so we get all the tuples it contains. Then in the SELECT, we use the COUNT(*) function to count how many tuples there are.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> COUNT(*)
<span class="hljs-keyword">FROM</span> (
        <span class="hljs-keyword">SELECT</span> PersonFK
        <span class="hljs-keyword">FROM</span> Rental
        <span class="hljs-keyword">UNION</span>
        <span class="hljs-keyword">SELECT</span> PersonFK
        <span class="hljs-keyword">FROM</span> CarOwnership
    ) <span class="hljs-keyword">AS</span> PersonTable;
</code></pre>
<p>It’s also important here to provide an <strong>alias</strong> to the <strong>subquery</strong>, because when subqueries appear in the FROM clause, the DBMS needs them to have aliases to distinguish them and avoid ambiguities regarding the origin of the attributes that are later selected or used in other clauses.</p>
<p>Continuing with the different set theory operators that SQL offers, we have <strong>INTERSECT</strong>, which combines the results of several tables to return a set with all the tuples that appear in <strong>all the tables simultaneously</strong>. To understand this, we have the query below that retrieves information about all the people who have a driver's license and have also rented at least one bike.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> DR.PersonFK <span class="hljs-keyword">AS</span> PersonID
<span class="hljs-keyword">FROM</span> DrivingLicenseRequest DR <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> DrivingLicense DL 
  <span class="hljs-keyword">ON</span> DR.LicenseID = DL.LicenseID
<span class="hljs-keyword">INTERSECT</span>
<span class="hljs-keyword">SELECT</span> R.PersonFK
<span class="hljs-keyword">FROM</span> Rental R;
</code></pre>
<p>We could write this query using only JOIN operations. But this time it might be more natural and straightforward to think of it as a set operation.</p>
<p>First, as shown above, we can construct a query that returns the identifier of all the people who currently have an active driver's license. To do this, we perform a JOIN between <strong>DrivingLicenseRequest</strong> and <strong>DrivingLicense</strong>, so we can gather the driver's license information with the <strong>foreign key PersonFK</strong> from DrivingLicenseRequest, which identifies the person who applied for the license. Then, we can construct another query that returns all the people who have rented at least one bike using the foreign key PersonFK from the Rental table.</p>
<p>And finally, to know which people have a driver's license and have also rented at least one bike, we need to keep the tuples that are in both tables. In other words, if the tables are multisets containing tuples, we need to keep those that appear in both multisets at the same time.</p>
<p>Instead of using the UNION operation, which represents the <strong>union of sets,</strong> we can use INTERSECT. It performs the <strong>intersection</strong> between sets, resulting in the final table of the query where we only have those people who meet all the conditions.</p>
<p>In the previous query, we only got the identifier of each person, since knowing the value of their primary key <strong>{PersonID}</strong> is enough to uniquely identify a person. With the foreign keys <strong>PersonFK</strong> pointing to the primary key <strong>{PersonID}</strong> of the Person table, we don't need the query to return more information about the person, as we can identify them with their primary key.</p>
<p>But there are situations where we may want to get more information about the person in the same query, such as their name in addition to the identification. So, if we needed to modify the query to return this, the simplest way would be to use a WITH clause that stores the identifiers of the people and then perform an INNER JOIN with the Person table in the body of the query, thus obtaining all the information present in the Person table.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> DR.PersonFK <span class="hljs-keyword">AS</span> PersonID, (<span class="hljs-keyword">SELECT</span> <span class="hljs-type">Name</span> <span class="hljs-keyword">FROM</span> Person <span class="hljs-keyword">WHERE</span> PersonID=DR.PersonFK)
<span class="hljs-keyword">FROM</span> DrivingLicenseRequest DR <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> DrivingLicense DL 
  <span class="hljs-keyword">ON</span> DR.LicenseID = DL.LicenseID
<span class="hljs-keyword">INTERSECT</span>
<span class="hljs-keyword">SELECT</span> R.PersonFK, (<span class="hljs-keyword">SELECT</span> <span class="hljs-type">Name</span> <span class="hljs-keyword">FROM</span> Person <span class="hljs-keyword">WHERE</span> PersonID=R.PersonFK)
<span class="hljs-keyword">FROM</span> Rental R
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> PersonID;
</code></pre>
<p>But to illustrate other ways to get more information about people in the system from their identification in the same query without using WITH, we have the option to use subqueries in the SELECT clause, as you can see in the example above. Specifically, if we only need to return the name in addition to the PersonID, we can create a correlated subquery that, for each tuple to be returned, gets the name of the person with a specific identifier. In other words, it searches the Person table for the tuple with a certain PersonID, retrieves the name, and adds it as an additional column.</p>
<p>In general, using correlated subqueries in the SELECT is not a good practice because, as you might guess, the result of the subquery must be computed for each tuple to be returned. This also complicates maintenance, code clarity, and makes optimization by the DBMS more difficult in most cases.</p>
<p>Basically, with a simple WITH and an INNER JOIN, you can avoid having to traverse the entire Person table for each person to obtain a specific characteristic, instead gathering data from both the intermediate table of the WITH and the Person table.</p>
<p>Just like with other set theory operators, INTERSECT takes multisets as input and by default outputs a set, so there can't be duplicate tuples in the output table, as we saw earlier with UNION. So if we need to force the operator to always work with multisets and also return a multiset as the output of the <strong>intersection operation</strong>, we can add the ALL modifier, as shown in the example query below:</p>
<pre><code class="lang-pgsql">
<span class="hljs-keyword">SELECT</span> BikeFK <span class="hljs-keyword">AS</span> BikeID
<span class="hljs-keyword">FROM</span> Rental
<span class="hljs-keyword">WHERE</span> StartTimestamp &gt;= <span class="hljs-string">'2024-01-01'</span>
<span class="hljs-keyword">INTERSECT</span> <span class="hljs-keyword">ALL</span>
<span class="hljs-keyword">SELECT</span> BikeFK
<span class="hljs-keyword">FROM</span> Rental
<span class="hljs-keyword">WHERE</span> Duration &lt;= <span class="hljs-number">3</span>
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> BikeID;
</code></pre>
<p>In this query, we get information on bikes that have been rented at least once during or after 2024 and whose rental duration was at most 3 hours. To do this, we construct a query that gets all bikes that have had at least one rental on a date <strong>&gt;= '2024-01-01'</strong>, and then another that gets those that have had at least one rental with a maximum duration of 3 hours.</p>
<p>Then, to keep the bikes that meet both conditions at once, we perform the intersection between the multisets returned by the queries, keeping the tuples that are in both multisets at once. And, since the same bike may have had several rentals with these characteristics, there may be duplicates in the final query table. If we want to preserve them, we’ll have to add the ALL modifier.</p>
<p>By default, we don’t usually use ALL in this type of query, since we simply want to know which bikes meet the conditions. But it’s possible that, due to some user requirement, the query needs to return duplicates, in which case we’d use ALL.</p>
<p>In most situations, the performance is similar enough to be negligible. But the more data there is in the database, the more noticeable the difference in performance will be between using ALL or not. This also depends on the <a target="_blank" href="https://stackoverflow.com/questions/1111707/what-is-the-difference-between-a-hash-join-and-a-merge-join-oracle-rdbms">algorithms</a> the DBMS uses internally to implement this operation.</p>
<p>The last set operator we'll look at here is EXCEPT, which is called MINUS in some DBMS. Basically, it implements the difference operation between sets, meaning if we have several sets A and B with tuples, the difference A-B returns a set with all the tuples that <strong>are</strong> in A and <strong>are not</strong> in B.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> p.EntryFK, p.PersonFK, p.PoolFK
<span class="hljs-keyword">FROM</span> PoolSanction p
<span class="hljs-keyword">WHERE</span> p.BanEndDate &lt; <span class="hljs-built_in">CURRENT_DATE</span>
<span class="hljs-keyword">EXCEPT</span>
<span class="hljs-keyword">SELECT</span> p.EntryFK, p.PersonFK, p.PoolFK
<span class="hljs-keyword">FROM</span> PoolSanction p <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Sanction s <span class="hljs-keyword">ON</span> p.SanctionID = s.SanctionID
<span class="hljs-keyword">WHERE</span> s.Status = <span class="hljs-string">'active'</span>;
</code></pre>
<p>For example, in the query above, we get information about all pool sanctions where the ban end date is before the current date when the query is run and that aren’t active.</p>
<p>As always, to do this, we might think the simplest way is through JOIN operations and a WHERE clause where the conditions are implemented. But to illustrate the use of EXCEPT, we can frame the query as finding all sanctions that meet the first condition of having a ban end date before CURRENT_DATE, and then from all of them, selecting only those that aren’t active. That is, from all those that meet the date condition, we keep only those that aren’t active.</p>
<p>Viewed another way, by getting all those that meet the date condition, we get a set A with tuples, where each one represents a sanction. Among all of them, there may be some that are active and some that are not. So to keep the ones we’re interested in, we need to remove from set A all those that are active. In other words, if we consider all the active ones to be in another set called B, then the sanctions we are interested in will be in the difference A-B (this means all the sanctions that meet the date condition (are in A) and are not active (are not in B)).</p>
<p>So in the query, you can see that we use the EXCEPT operator to work with the queries that get sets A and B, respectively. That is, the first query constructs set A by imposing the condition <strong>p.BanEndDate &lt; CURRENT_DATE</strong> on the tuples of <strong>PoolSanction</strong>, while the query following the EXCEPT operator constructs set B by imposing the condition <strong>s.Status = 'active'</strong>, gathering data from PoolSanction and Sanction to filter by the Status attribute, which is in Sanction instead of PoolSanction.</p>
<p>To implement the difference A-B, we use EXCEPT, where the query above the EXCEPT is set A and the one below is set B. This is important to keep in mind because EXCEPT is the only operator where the order of the operands can change the result of the query.</p>
<p>For example, with the other operators <strong>UNION</strong> and <strong>INTERSECT</strong>, we can clearly see that it doesn't matter if we unite or intersect several sets A and B or B and A – in any order, the result will be the same. This is not the case with the difference A-B, which doesn't necessarily have to be equivalent to B-A. This property is called <strong>commutativity</strong>, and EXCEPT is the only set operator that <strong>is not commutative</strong>.</p>
<p>Ultimately, in this query, we can see that the table aliases are all in lowercase. This is allowed in SQL, and we can even declare an alias in uppercase and then use it in lowercase, or vice versa. But if we enclose the aliases in quotes, like in <strong>Person "P"</strong>, we can only refer to the table with the alias exactly as it’s written in the quotes.</p>
<p>On one hand, not quoting it provides flexibility when writing the code, as we don’t need to remember exactly how it was written. In most SQL code, quotes aren’t commonly used. But, this can cause ambiguity issues if the alias is named exactly the same as a table or another element in the database. Quoting it avoids these potential collisions with names of other elements.</p>
<p>In the end, the decision of which alias to assign to each table or element in the query mainly depends on its complexity and the style guide followed, among other factors.</p>
<p>Just like with other set operators, EXCEPT also takes multisets as input by default and returns sets, removing any duplicate tuples. So if we need to keep those duplicate tuples, we simply need to add the ALL modifier.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> BikeFK <span class="hljs-keyword">AS</span> BikeID
<span class="hljs-keyword">FROM</span> Rental
<span class="hljs-keyword">EXCEPT</span> <span class="hljs-keyword">ALL</span>
<span class="hljs-keyword">SELECT</span> BikeFK
<span class="hljs-keyword">FROM</span> Rental
<span class="hljs-keyword">WHERE</span> Duration &lt; <span class="hljs-number">2</span>;
</code></pre>
<p>For example, in this query, we get information on all the bikes that have been rented <strong>at least</strong> once and have never been rented for less than 2 hours.</p>
<p>To implement this, we first construct a query that retrieves all the bikes that have been rented at least once using the foreign key attribute <strong>BikeFK</strong> from the <strong>Rental</strong> table. Then, with another query, we get all the bikes that have been rented at least once for less than 2 hours. Finally, to keep only those we’re interested in, we get the difference between the first set and the second.</p>
<p>As you can see, a bike may have been rented an arbitrary number of times, so the first query might return many duplicate tuples. If we don't use the ALL modifier, all those duplicates will be lost, resulting in a table where each bike is guaranteed to appear at most once.</p>
<p>But if we want to keep the duplicates, simply using ALL will show that the query returns a result table with many more tuples, as many of them correspond to duplicate bikes.</p>
<p>Here, we also need to consider that, despite the possibility of duplicate bikes existing in both set A and set B, when we perform the difference A-B using <strong>EXCEPT</strong>, we won't get any bike that's in B, regardless of how many times it's duplicated in both sets, one, or neither.</p>
<p>But when performing the operation using EXCEPT ALL, if we have <strong>x repetitions</strong> of a tuple in set A and <strong>y repetitions</strong> of that same tuple in B, then in the resulting table, we will get <strong>max{x-y,0}</strong> repetitions of that tuple. That is, when there are more repetitions in A than in B, we will get <strong>x-y</strong> repetitions of the tuple in the final table. If there are more repetitions in B than in A, then <strong>x-y</strong> is <strong>negative</strong>, so we will simply get 0 repetitions of the tuple. This means that tuple won’t appear in the resulting table of the <strong>difference operation</strong> implemented with <strong>EXCEPT ALL</strong>.</p>
<p>To correctly understand the <strong>difference operator,</strong> let's consider a query where we need to get information on all cruise trips for which there is no return trip. In other words, we want to find all trips going from a <strong>city x</strong> to another <strong>city y</strong> with no return to city x.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> V.DepartureCityFK, V.ArrivalCityFK
<span class="hljs-keyword">FROM</span> Voyage V
<span class="hljs-keyword">EXCEPT</span>
<span class="hljs-keyword">SELECT</span> V2.ArrivalCityFK, V2.DepartureCityFK
<span class="hljs-keyword">FROM</span> Voyage V2
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> DepartureCityFK, ArrivalCityFK;
</code></pre>
<p>The approach we'll take for this query is based on set theory, as it’s particularly easy to solve in this case. First, we construct a query that returns all existing trips. From these, we can get all the information present in the Voyage table – but for simplicity, we'll only focus on the attributes that determine the departure and arrival cities of the trip (which are their foreign keys <strong>DepartureCityFK</strong> and <strong>ArrivalCityFK)</strong>.</p>
<p>Then, from all those trips returned by the first query, we need to remove the return trips. That is, for each existing trip that departs from city x and arrives at city y, we look for a <strong>return trip</strong> in the Voyage table that departs from city y and arrives at city x. If it exists, we remove the original trip from the result table of the first query.</p>
<p>We could implement this using the IN operator and a subquery. But it's simpler and more efficient to build a second query that gets all the trips from Voyage but swaps the departure and arrival cities for each trip as shown above. This second query is responsible for getting all possible return trips that might exist by swapping the values of the foreign keys <strong>DepartureCityFK</strong> and <strong>ArrivalCityFK</strong>, meaning swapping the departure cities with the arrival cities.</p>
<p>Finally, with these two queries, we apply the <strong>EXCEPT</strong> operator, where we remove from the result table of the first query (which contains all the trips from Voyage) all those contained in the result table of the second query. In other words, from all existing trips, we are removing those considered return trips because they were generated by the second query by swapping the departure and arrival cities.</p>
<p>Even if some of those return trips don't exist in <strong>Voyage</strong> (which can happen), the EXCEPT operator will simply ignore that tuple to remove since it doesn't exist in the set from which it needs to be removed.</p>
<p>To wrap up this type of query, so far we have seen some that apply a single set operator. But SQL allows us to use any number of them in the same query or subquery as needed. This is applied in the query below, which retrieves information about all the people who have or have had a driver's license application registered in the database, or an approved license, and who have never had a rejected application.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> Persons <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> DR.PersonFK
    <span class="hljs-keyword">FROM</span> DrivingLicenseRequest DR
        <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> DrivingLicense DL <span class="hljs-keyword">ON</span> DR.LicenseID = DL.LicenseID
    <span class="hljs-keyword">UNION</span>
    <span class="hljs-keyword">SELECT</span> DR2.PersonFK
    <span class="hljs-keyword">FROM</span> DrivingLicenseRequest DR2
    <span class="hljs-keyword">EXCEPT</span>
    <span class="hljs-keyword">SELECT</span> DR3.PersonFK
    <span class="hljs-keyword">FROM</span> DrivingLicenseRequest DR3
        <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> RejectedDrivingLicense RD <span class="hljs-keyword">ON</span> DR3.LicenseID = RD.LicenseID
)
<span class="hljs-keyword">SELECT</span> PersonFK
<span class="hljs-keyword">FROM</span> Persons
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> PersonFK;
</code></pre>
<p>Regarding the implementation, we can see that in the first query used to build the intermediate table Persons, we get all the people who have or have had an accepted driver's license by using an INNER JOIN between the DrivingLicenseRequest and DrivingLicense tables. This way, with the data from DrivingLicenseRequest, we can access the foreign key PersonFK that identifies the person who made the application.</p>
<p>Then, we make a union with a second query that retrieves people who have made an application, whether pending, accepted, or rejected. This time we get the data from the DrivingLicenseRequest table, which encompasses all existing applications in the database.</p>
<p>By performing the union, we get all the people who have or have had pending, accepted, or rejected applications, since the first query returns only those with an approved license – but the second returns people who have also had rejected applications.</p>
<p>To exclude those with rejected applications, the EXTENT operator is used along with another query that retrieves these people with rejected applications. So they are all excluded from the final query result – or rather from the intermediate table Persons. From this table, we finally get all its tuples and order them by the attribute PersonFK – that is, by the identifier of the people we obtain.</p>
<p>As you can see, the order in which set operations are performed is from top to bottom. That is, these operators act on tables containing query results, so SQL performs these operations in a top-down order (although we can use parentheses to change the precedence of the operators according to the needs of the query). Also, in this case, we can see that the UNION operation is redundant since everything contained in the first query is also contained in the second.</p>
<p>In other words, the second query retrieves people who have or have had applications of any type, whether pending, accepted, or rejected, so all the people who have had accepted applications are included in this set of people generated by the second query. In a real-world environment, we should optimize it by dispensing with the first query, which also implies the elimination of the UNION operation. But here we leave it as is to illustrate its equivalence with the optimized query we have described.</p>
<h3 id="heading-aggregation-queries">Aggregation Queries</h3>
<p>Next, we’ll look at a type of query that’s often used in temporal data analysis, calculating metrics, building dashboards aimed at strategic decision-making, and so on. These are <strong>aggregation queries</strong>, and they’re based on treating the tuples of a table as if they were groups on which we can perform certain operations. For example, we can use them to sum all the values of an attribute in a certain group, find their average, and calculate the maximum or minimum value, among others.</p>
<p>As you might guess, the basic statements to implement this type of query are GROUP BY, HAVING, and the different aggregation functions offered by SQL.</p>
<p>With GROUP BY, we can choose a series of attributes whose values will determine how we form groups of tuples in a particular table. This means that each of these groups will be formed by a combination of values taken by the selected attributes. Then with the aggregation functions, we will calculate a certain metric for each group. w</p>
<p>With HAVING, we’ll impose conditions related to the characteristics of each group, mainly the value taken by the metrics we calculate on them.</p>
<p>To understand all this with examples, let's first consider a query where we want to get a list of all the nationalities present in the Person table and the number of people with each nationality.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> Nationality, COUNT(*) <span class="hljs-keyword">AS</span> NumPersons
<span class="hljs-keyword">FROM</span> Person
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> Nationality
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> NumPersons <span class="hljs-keyword">DESC</span>;
</code></pre>
<p>At first glance, we realize that we need to count a certain number of people for each value that the <strong>Nationality</strong> attribute takes. So, the approaches we've seen so far aren’t straightforward for performing this operation (which in some cases may not be possible without grouping).</p>
<p>For example, here we could list all the different nationalities that appear in Nationality and, for each one, use a subquery in the SELECT statement to count how many people in the Person table have that nationality.</p>
<p>But this approach would be very inefficient since, for each different nationality, we would have to go through the entire Person table looking for people with that nationality. Even though these searches can be optimized, they are generally not as efficient as the approach we’re going to follow using grouping.</p>
<p>Instead, we use <strong>grouping</strong> with the <strong>GROUP BY</strong> statement. Specifically, we indicate the table attributes that guide generating the tuple groups in the table. In this case, since we want to calculate a metric for each value of the <strong>Nationality</strong> attribute, we use that attribute to group the tuples. This way, for <strong>each value</strong> of that attribute, a <strong>group of tuples</strong> is generated, represented by that value, which will represent all the people with that same nationality.</p>
<p>Then, if we want to count how many people have that nationality, we simply count how many tuples each group has. So, in the SELECT statement, we add an extra attribute where we use <strong>COUNT(*)</strong>. This time it won’t count all the tuples in the table, but those in each group. Since using GROUP BY makes it mandatory to return in the SELECT the attributes we are grouping by, the final table will only show the distinct values of Nationality, meaning the "representative" values of each group of tuples.</p>
<p>For each of those values, we’ll attach the value of <strong>COUNT(*)</strong> in the same tuple of the output table, which will correspond to the <strong>number of tuples</strong> in the corresponding <strong>group</strong>. This conceptually represents the number of people with that nationality.</p>
<p>Finally, we can apply sorting with the ORDER BY statement – but we should keep in mind that we can only sort in this case with respect to the attributes we return in SELECT. This is because in the query, we’re creating groups represented by Nationality values, which means we can’t "return" the rest of the attributes in the SELECT as we did before.</p>
<p>We can only calculate metrics with them and return those – but not the attributes themselves with all their values. This is because when grouping, the resulting table necessarily contains <strong>only the "representative" values</strong> of each group and metrics of other attributes calculated from those groups (or metrics of the group itself, such as the number of tuples it has in this case).</p>
<p>There are various metrics we can calculate with the basic <strong>aggregation functions</strong> that SQL provides by default. Below we see a query where we get, for each possible pool status, the smallest minimum depth and the largest maximum depth of the pools with that status, as well as the average depth and the number of pools in that status.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> Status,
    MIN(MinDepth) <span class="hljs-keyword">AS</span> Shallowest,
    AVG((MinDepth + MaxDepth) / <span class="hljs-number">2.0</span>) <span class="hljs-keyword">AS</span> AvgDepth,
    MAX(MaxDepth) <span class="hljs-keyword">AS</span> Deepest,
    COUNT(*) <span class="hljs-keyword">AS</span> NumPools
<span class="hljs-keyword">FROM</span> Pool
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> Status;
</code></pre>
<p>The implementation of this query is very similar to the previous one, as we need to group the Pool tuples by the values of their Status attribute, which determines the status of the pools.</p>
<p>So in the GROUP BY clause, we only specify the Status attribute. This way, we group the tuples into as many groups as there are values present in the Status attribute in the table, and in each of these groups, we have all the tuples representing pools in that status.</p>
<p>So along with the information for each status, we can calculate metrics for its associated group of tuples – that is, for the pools in that status. For example, with <strong>MIN(MinDepth)</strong>, we get the smallest value of the <strong>MinDepth</strong> attribute present in the group for which this metric is being calculated. In this case, it represents the smallest minimum depth of all pools in a certain status.</p>
<p>Similarly, with the aggregation operation <strong>MAX(MaxDepth)</strong>, we get the largest maximum depth, or in other words, the largest value of the MaxDepth attribute in the corresponding group of pools. With COUNT(*), we get the number of pools in each group.</p>
<p>On the other hand, the average depth associated with the pools in each group is calculated with <strong>AVG((MinDepth + MaxDepth) / 2.0)</strong>. First, it’s worth noting that both in the SELECT clause and in the input argument of an aggregation function like AVG(), we can perform arithmetic operations on the attributes.</p>
<p>For example, in this case, with <strong>(MinDepth + MaxDepth) / 2.0</strong>, we calculate the average value between the minimum and maximum depth of <strong>each pool</strong> – not of each group, but of each tuple in the group – all using decimal values like 2.0 so that the result isn’t automatically rounded to an integer. Then, with this value calculated for each tuple, we use the aggregation function <strong>AVG()</strong> to calculate the average of this value for each group.</p>
<p>That is, with <strong>(MinDepth + MaxDepth) / 2.0</strong>, we get a certain value for each tuple, and then with <strong>AVG()</strong>, we take all those calculated values for the tuples of a certain group and calculate their average. Thus, for each possible state of a pool, we obtain the average depth of all the pools in that state, first calculating the average depth of each pool and then calculating the average of these depths across all pools in a certain state.</p>
<p>But, in addition to calculating metrics for each group of tuples, we might need to keep only those groups whose metrics meet certain conditions, depending on the query to be resolved. For example, here we consider a query where we get, for each person, the number of bike rentals they have made since records began, as long as that person has made at least three rentals.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.PersonID,
    P.Name,
    COUNT(*) <span class="hljs-keyword">AS</span> RentalCount
<span class="hljs-keyword">FROM</span> Rental R
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P <span class="hljs-keyword">ON</span> R.PersonFK = P.PersonID
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> P.PersonID, P.Name
<span class="hljs-keyword">HAVING</span> COUNT(*) &gt; <span class="hljs-number">2</span>
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> RentalCount;
</code></pre>
<p>To implement this query, we might have considered using a correlated subquery in the SELECT statement that counts how many tuples in Rental have their foreign key PersonFK pointing to each person. But this would be inefficient, since groupings are usually much faster for this type of task.</p>
<p>It’s also <strong>not possible</strong> to impose a condition <strong>WHERE COUNT(*) &gt; 2</strong>, either in the subquery of the SELECT clause or in the main query (in general, conditions on aggregation functions can’t be imposed in a WHERE clause). So in this case, we would have to use another subquery in the WHERE clause that counts the number of rentals each person has and that then checks that this number is &gt; 2.</p>
<p>To avoid using subqueries and make our implementation as fast as possible, we first perform an INNER JOIN between the Rental and Person tables. We combine all their information into tuples of their Cartesian product where we have rentals and data about the person who made them. We can do this by imposing the condition in the JOIN that the foreign key PersonFK of Rental points to the PersonID identifier of its same tuple in the Cartesian product.</p>
<p>After performing the JOIN, we use the GROUP BY clause to group the resulting tuples by the PersonID and Name attributes of the person table. We do this because we want to calculate a metric for each person, so we have to include their identifier (primary key) in the grouping of the GROUP BY statement (meaning all the attributes that form their primary key).</p>
<p>Also, since we want to return each person's name along with their identifier, we can include the Name attribute in the GROUP BY. But it's important to note that the attributes we group by must uniquely identify each group of tuples that is formed.</p>
<p>In other words, by grouping by <strong>PersonID</strong>, we are forming groups of tuples that contain all the rentals made by a certain person, identified by a value of their primary key PersonID. This serves as the "representative" of the group of tuples.</p>
<p>But since this PersonID attribute is enough to identify the group, it's fine if we include more information about the person in this "representative value" of the group. So instead of containing only their primary key, it includes more information about the person, like their name.</p>
<p>As you can guess, if instead of grouping by <strong>{PersonID}</strong> we group by a <strong>candidate key</strong> (or rather a <strong>superkey</strong> as in this case <strong>{PersonID, Name}</strong>), we’ll get the same groups as grouping by {PersonID}. This means that the same number of groups will still be generated as there are people in the table (since with a superkey we can <strong>uniquely identify each person, and therefore each group)</strong>.</p>
<p>Adding the <strong>Name</strong> attribute to the grouping is not an arbitrary decision – we have to use the Name attribute in the SELECT statement. When using GROUP BY, we can only return in the SELECT statement those attributes that we have used in the GROUP BY clause (so, those we have used for grouping). So to get the person's name and not just their identifier, one option is to include the attribute in the GROUP BY so we can return it in the SELECT – or in other words, use the <strong>Name</strong> attribute for grouping.</p>
<p>But, this won’t always work because there are times when we group by an attribute A and want to return information about another attribute B. But for <strong>each value</strong> of <strong>attribute A</strong>, we have <strong>multiple tuples</strong> with <strong>multiple different values</strong> in attribute B. This prevents us from using B for grouping, although we can still calculate metrics on B.</p>
<p>On the other hand, to count how many rentals each person has made, we just need to use the aggregation function COUNT(*) after grouping by <strong>{PersonID, Name}</strong>. This forms groups of tuples from the Cartesian product where we have the same information for the same person, but each represents a different rental. By counting how many tuples each group has, we get the number of rentals made.</p>
<p>To get only those groups (people) who have made more than 2 rentals, we use the <strong>HAVING</strong> clause to impose that condition, since aggregation functions can’t be used in the WHERE clause. Also, we can’t use the alias given to the attribute constructed with <strong>COUNT(*)</strong> that’s returned in the SELECT in HAVING. Instead, we need to rewrite the definition of the attribute in HAVING.</p>
<p>That is, just like with WHERE, we can’t impose conditions on the attributes or columns of the resulting table we return by simply referring to their aliases – we have to use their definitions, as in this case with <strong>COUNT(*)</strong>.</p>
<p>It's worth noting that including the Name attribute in the GROUP BY to <strong>"return"</strong> it in the SELECT isn’t the only option we have to do this (or even to get more information about the person). We always have the option to save the query result in an intermediate table with a WITH clause and then join it with the Person table or the appropriate one.</p>
<p>But we have another option, as shown below, which involves grouping only by the <strong>PersonID attribute</strong> and then using correlated subqueries in the SELECT to get the rest of the information for each person.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.PersonID,
    (<span class="hljs-keyword">SELECT</span> <span class="hljs-type">Name</span> <span class="hljs-keyword">FROM</span> Person <span class="hljs-keyword">WHERE</span> PersonID=P.PersonID),
    COUNT(*) <span class="hljs-keyword">AS</span> RentalCount
<span class="hljs-keyword">FROM</span> Rental R
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P <span class="hljs-keyword">ON</span> R.PersonFK = P.PersonID
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> P.PersonID
<span class="hljs-keyword">HAVING</span> COUNT(*) &gt; <span class="hljs-number">2</span>
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> RentalCount;
</code></pre>
<p>But this option isn’t the most optimal: as with a <strong>correlated subquery</strong> in the SELECT, we can only add one attribute of information per subquery. This forces us to use one subquery per attribute we want to add, which is very inefficient as you can see. Also, correlating the subqueries reduces maintainability and possibly also the clarity of the code, which are qualities worth considering.</p>
<p>With these queries, we have seen how we can use <strong>GROUP BY</strong> to group tuples by one attribute, or even several if we need to add more information to the resulting table from the query. Also, we’ve seen the correct way to impose conditions on expressions with aggregation functions, which is by using the HAVING clause.</p>
<p>But, we’re not always trying to return more information to the user every time we use multiple attributes in the GROUP BY statement. Sometimes, we need to group tuples by more than one attribute.</p>
<p>For example, in the query below, we get all the <strong>person-pool pairs</strong> (only those present in CityPool) that exist in the system. Then for each of them, we calculate the average duration the user has spent in that pool across all their entries.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> E.PersonFK <span class="hljs-keyword">AS</span> PersonID,
    E.PoolFK <span class="hljs-keyword">AS</span> PoolID,
    COUNT(*) <span class="hljs-keyword">AS</span> VisitCount,
    AVG(E.Duration) <span class="hljs-keyword">AS</span> AvgDuration
<span class="hljs-keyword">FROM</span> Entry E
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> E.PersonFK, E.PoolFK
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> E.PersonFK, E.PoolFK;
</code></pre>
<p>As you can see, we get the data from the Entry table, where we have to perform a grouping with the attributes <strong>PersonFK</strong> and <strong>PoolFK</strong>, since we need to calculate metrics for each person-pool pair. With this grouping, each pair of person-pool values is a group formed by all the tuples in Entry that represent times the person entered that pool.</p>
<p>In this way, with <strong>AVG(E.Duration)</strong>, we calculate the average of the <strong>Duration</strong> attribute for each group (so how long, on average, a person stayed at the pool on each visit) while COUNT(*) counts the number of those entries.</p>
<p>Finally, it's important to note that in this query, we’re only getting the person-pool pairs that appear in the Entry table – we’re not constructing all possible pairs. So we won't find any tuple in the resulting table of the query where a person has never entered a certain pool.</p>
<p>If we wanted to include this information, we would need to structure the query differently, constructing all combinations of person-pool in an intermediate table and then calculating how many entries each person has in each pool in another way (either using subqueries, <strong>OUTER JOIN</strong> operations, or even more advanced functions that aren’t covered here).</p>
<p>In the GROUP BY clause, we can use an arbitrary number of attributes for grouping. The query below shows how we can get the number of times the cruise has traveled that route and the sum of the distances covered on those trips for each cruise and route between two ports. We can also display the information of the cities where those ports are located.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> V.ShipFK <span class="hljs-keyword">AS</span> ShipID,
    V.DepartureNameFK <span class="hljs-keyword">AS</span> DeparturePort,
    V.DepartureCityFK <span class="hljs-keyword">AS</span> DepartureCity,
    V.ArrivalNameFK <span class="hljs-keyword">AS</span> ArrivalPort,
    V.ArrivalCityFK <span class="hljs-keyword">AS</span> ArrivalCity,
    COUNT(*) <span class="hljs-keyword">AS</span> TripCount,
    SUM(V.Distance) <span class="hljs-keyword">AS</span> TotalDistance
<span class="hljs-keyword">FROM</span> Voyage V
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> V.ShipFK,
    V.DepartureNameFK,
    V.DepartureCityFK,
    V.ArrivalNameFK,
    V.ArrivalCityFK
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> V.ShipFK, TotalDistance <span class="hljs-keyword">DESC</span>;
</code></pre>
<p>As you can see, in this case, we get all this information from the <strong>Voyage</strong> table, as it has multiple foreign keys to <strong>CruiseShip</strong> and <strong>Port</strong>, as well as <strong>City</strong>. These can help us implement this query easily.</p>
<p>Of all the attributes it has, we group by <strong>ShipFK</strong>, <strong>DepartureNameFK</strong>, <strong>DepartureCityFK</strong>, <strong>ArrivalNameFK</strong>, and <strong>ArrivalCityFK</strong>. This allows us to group the tuples of the Voyage table based on the combinations of values representing a <strong>cruise-route pair</strong> (where a <strong>route</strong> is considered as a <strong>pair of ports</strong> along with the city values where they are located).</p>
<p>These are <strong>redundant</strong> for the grouping itself, as clearly all ports belong to one and only one city (according to the domain). But if we want to know the city where the port is located, the simplest option is to include the <strong>DepartureCityFK</strong> and <strong>ArrivalCityFK</strong> attributes in the grouping so we can return them in the SELECT.</p>
<p>So for each cruise-route pair, we can count how many trips the cruise has made on that route using <strong>COUNT(*)</strong>, and with <strong>SUM(V.Distance)</strong> we can get the sum of all distances covered on those trips (as the tuples of each group in this case are the trips the cruise makes or has made on the corresponding route).</p>
<p>On the other hand, in this type of query, it’s also common to use the DISTINCT modifier to count values in a group or perform a specific aggregation operation on them. For example, in the query below, we get all the people who have ever lived in a city. Then for each of them, we count how many <strong>different cities</strong> they have lived in.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> R.PersonFK <span class="hljs-keyword">AS</span> PersonID,
    COUNT(<span class="hljs-keyword">DISTINCT</span> R.CityFK) <span class="hljs-keyword">AS</span> NumCities
<span class="hljs-keyword">FROM</span> Residence R
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> R.PersonFK
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> NumCities <span class="hljs-keyword">DESC</span>;
</code></pre>
<p>To do this, we use the data stored in the <strong>Residence</strong> table, which has a foreign key PersonFK that can determine, in each tuple, the person associated with that residence record. Since we want to calculate a certain metric for each person who has had at least one residence, we group by the PersonFK attribute, as selecting data from the Residence table ensures that all these people have or have had at least one residence record.</p>
<p>Then, for each group of tuples formed, we could use COUNT(*) to count how many residences the "representative" person of each group has had. But in this case, we want to count the number of <strong>different cities</strong> they have lived in.</p>
<p>To do this, we will give COUNT() the <strong>CityFK</strong> attribute as the input argument, which is a foreign key that determines the city associated with a residence record. This would count all the values the CityFK attribute takes for each group, but not the distinct values. So, we’ll need to add the <strong>DISTINCT</strong> modifier before the attribute and inside the COUNT() aggregation function so that it only counts the distinct values that the <strong>CityFK</strong> attribute takes in each group. This corresponds to the number of different cities a certain person has been associated with through Residence, meaning where they have lived.</p>
<p>When using the DISTINCT modifier in aggregation functions, we may also need to apply conditions on these aggregation functions. So we’ll need to use the same DISTINCT modifier in other clauses like <strong>HAVING</strong>, in addition to <strong>SELECT</strong> where most aggregations are calculated and returned.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> PersonsTable <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> CB.PersonFK <span class="hljs-keyword">AS</span> PersonID,
        COUNT(<span class="hljs-keyword">DISTINCT</span> CB.PaymentMethod) <span class="hljs-keyword">AS</span> NumPaymentMethods
    <span class="hljs-keyword">FROM</span> CruiseBooking CB
    <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> CB.PersonFK
    <span class="hljs-keyword">HAVING</span> COUNT(<span class="hljs-keyword">DISTINCT</span> CB.PaymentMethod) &gt; <span class="hljs-number">1</span>
    <span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> NumPaymentMethods <span class="hljs-keyword">DESC</span>
)
<span class="hljs-keyword">SELECT</span> *
<span class="hljs-keyword">FROM</span> PersonsTable PT
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Person P <span class="hljs-keyword">USING</span> (PersonID);
</code></pre>
<p>For example, above we have a query that retrieves information about all the people who have made at least one cruise booking. It also gets the number of different payment methods they have used to pay for all those bookings, as long as that number is at least two different payment methods.</p>
<p>First, to implement this query, we use the <strong>CruiseBooking</strong> table and group by <strong>PersonFK</strong> – as when needing to calculate a number for each person, we should group the tuples of the table by the <strong>PersonFK</strong> attribute. This way, each group corresponds to the bookings made by a certain person.</p>
<p>So we can easily use <strong>COUNT(DISTINCT CB.PaymentMethod)</strong> to count how many distinct values the <strong>PaymentMethod</strong> attribute takes in each group of tuples. This corresponds to the number of different payment methods the representative person of that group of tuples has used to pay for their bookings.</p>
<p>Also, to require that they’ve used at least two payment methods, we use a HAVING clause where we declare that the value returned by the aggregation function <strong>COUNT(DISTINCT CB.PaymentMethod)</strong> must be <strong>&gt;1</strong>.</p>
<p>We can’t use its alias name <strong>NumPaymentMethods</strong> to declare this condition (some DBMS allow it, but for portability reasons, it’s better to code it without using the alias in the condition), nor can we use a WHERE because it’s an aggregation function. The correct way is using a HAVING.</p>
<p>Although it may seem that the value of <strong>NumPaymentMethods</strong> is being calculated multiple times unnecessarily, internally the DBMS can optimize the query automatically to avoid this type of unnecessary calculation. But we still have to write the aggregation function multiple times: once to define the attribute <strong>NumPaymentMethods</strong> in the SELECT and another in the HAVING to impose a filtering condition on the tuples of the resulting table from a grouping.</p>
<p>Finally, we save the result of this grouping in an intermediate table called <strong>PersonsTable</strong>, where only the identifier of each person and their corresponding number of payment methods are stored. Later, we can use this intermediate table in a <strong>JOIN</strong> operation with the <strong>Person</strong> table. This will gather all the information of each person along with the attribute containing the number of payment methods in one table. Then this is ultimately returned as the query output to the user.</p>
<p>So as expected, if we use the <strong>DISTINCT</strong> modifier on an attribute in an aggregation function in the SELECT clause and want to impose a condition on it, we have to write it exactly as it appears in a <strong>HAVING</strong> clause – regardless of whether it uses the modifier or not, since we write it exactly as it appears in the SELECT.</p>
<p>So far, we have seen that we can give an aggregation function input attributes with which it will perform the corresponding aggregation operation. Also, if we need only the distinct values of a certain attribute or <strong>result of an arithmetic operation between attributes</strong>, we can add the DISTINCT modifier.</p>
<p>But DISTINCT is not only used for a single attribute – we can also use it to. getunique combinations of values from a series of attributes, or even unique results obtained from an arithmetic operation involving multiple attributes. For example, in the query below, we want to get all the cruises along with the number of pairs of departure and arrival cities they have visited throughout their journeys.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> V.ShipFK,
    COUNT(<span class="hljs-keyword">DISTINCT</span> (V.DepartureCityFK, V.ArrivalCityFK)) <span class="hljs-keyword">AS</span> NumRoutes
<span class="hljs-keyword">FROM</span> Voyage V
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> V.ShipFK
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> NumRoutes <span class="hljs-keyword">DESC</span>;
</code></pre>
<p>To do this, we simply group the tuples of the Voyage table by the ShipFK attribute, since we want to calculate a number for each cruise (and the ShipFK foreign key is what determines the cruise that made the journey). Thus, each group of tuples will be “represented” by a certain value of ShipFK that uniquely identifies a cruise. Those tuples, in turn, will represent all the journeys that cruise has made.</p>
<p>So to count how many <strong>distinct</strong> pairs of departure and arrival cities each cruise has traveled to, we can use the aggregation function <strong>COUNT(DISTINCT (V.DepartureCityFK, V.ArrivalCityFK))</strong>.</p>
<p>As you might guess, a cruise can make the same trip several times, which means that within the same group of tuples, we might find the same combination of values for the attributes <strong>(V.DepartureCityFK, V.ArrivalCityFK)</strong> multiple times. These attributes uniquely identify the departure and arrival cities of the trip, so if the trip is made several times, there must be several "duplicate" tuples – or at least tuples with the same values in those attributes, since there can be multiple different ports in the same city.</p>
<p>If we look at all the combinations of values that the attributes <strong>(V.DepartureCityFK, V.ArrivalCityFK)</strong> take in each group, we’ll see that they represent the departure and arrival cities of the cruise in each trip it has made. By applying the DISTINCT modifier, we treat each pair of values as if it were unique, and we keep all those that are unique. This refers to pairs of different departure and arrival cities in the group on which this aggregation operation is calculated, ignoring all duplicate pairs (which would inflate the count artificially). This would represent the total trips the ship has made.</p>
<p>Finally, when solving a query using grouping, we might need to calculate metrics using aggregation functions with the DISTINCT modifier. Because of this, we have to consider that if we need to impose a condition on that metric, we’ll need to use the aggregation function in the HAVING clause exactly as declared in the SELECT (with the same DISTINCT modifier and attributes present in the input argument of the aggregation function).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> CB.PersonFK <span class="hljs-keyword">AS</span> PersonID,
    COUNT(<span class="hljs-keyword">DISTINCT</span> (CB.CabinNumber, CB.PaymentMethod))
<span class="hljs-keyword">FROM</span> CruiseBooking CB
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> CB.PersonFK
<span class="hljs-keyword">HAVING</span> COUNT(<span class="hljs-keyword">DISTINCT</span> (CB.CabinNumber, CB.PaymentMethod)) &gt; <span class="hljs-number">1</span>
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> count <span class="hljs-keyword">DESC</span>;
</code></pre>
<p>For example, in the query above, we get the identifiers of certain people, and for each one, we calculate the number of distinct pairs composed of <strong>cabin number-payment method</strong> that the person has generated through their various CruiseBooking reservations in their name. Here, we’re only interested in those people whose number of pairs is at least two.</p>
<p>To implement this, we first group by the PersonFK attribute of the CruiseBooking table, as it contains all the information we need to calculate the previous metric for each person. This is why we only need to group by the foreign key PersonFK attribute. So for each group of CruiseBooking tuples, we’ll have all the reservations associated with a single person.</p>
<p>Then, with <strong>COUNT(DISTINCT (CB.CabinNumber, CB.PaymentMethod))</strong>, we can calculate the number of distinct combinations of values that the attributes <strong>(CB.CabinNumber, CB.PaymentMethod)</strong> take in the group of tuples. As you can see, when we want to count combinations of values from several attributes, we declare both attributes in a "tuple" <strong>(CB.CabinNumber, CB.PaymentMethod)</strong>, which we provide as input to the <strong>COUNT()</strong> aggregation function. We use the DISTINCT modifier to ensure it only counts distinct combinations of these two attributes.</p>
<p>Later, if we want to say that the result of the aggregation function has to be greater than 1 to consider the corresponding group of tuples in constructing the query output, we use the HAVING clause. In it, we can declare the condition by rewriting the aggregation function again in the HAVING clause in the same way we declared it in the SELECT.</p>
<p>Note that we haven't assigned an alias to the attribute we built with the aggregation function, so SQL automatically assigns the name <strong>“count”</strong> to this additional attribute. This corresponds to the name of the aggregation function used in its construction.</p>
<p>But if we create more attributes using the same aggregation function <strong>COUNT()</strong>, then all those attributes will be called <strong>“count”</strong> by default at the same time, creating an ambiguity problem. This is why it's essential to use aliases for attributes that are expected to be named the same way by SQL (the DBMS is responsible for assigning default aliases).</p>
<p>Finally, it's important to note that queries don't necessarily have to contain only one grouping. The GROUP BY clause can be used an indefinite number of times in a query, especially if it includes a subquery, which can use the GROUP BY clause again.</p>
<p>But it's important to remember that you can't have multiple groupings <strong>“at the same time”</strong> in the same query. In other words, if we use GROUP BY multiple times, it must be because our query consists of subqueries, with each subquery performing a grouping, avoiding doing them all at the same level. In other words, for each GROUP BY clause, there must be one and only one SELECT clause.</p>
<h3 id="heading-division-queries">Division Queries</h3>
<p>At this point, with everything we've seen, we have enough tools to solve practically any query with SQL. (But there are some that we won't focus on here because they require operating on data recursively or hierarchically, which is more complex.)</p>
<p>Now, we’ll look at a series of queries where we use these previous tools to implement a relational algebra operator that doesn't have a direct implementation in SQL. For example, we have seen that the <strong>SELECT</strong> statement represents the implementation of the <strong>projection</strong> operator in relational algebra. And other statements such as certain types of JOIN or UNION, INTERSECT, and EXCEPT have direct equivalent operators in relational algebra as well.</p>
<p>But the <strong>division</strong> operator doesn’t have an equivalent clause or function in SQL due to its nature. In short, if we have several tables, this operator is responsible for getting all the tuples from one of the tables that are <strong>“associated”</strong> with each and every tuple of the other table.</p>
<p>To understand how this works, let's consider the following example:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> R.PersonFK
<span class="hljs-keyword">FROM</span> Rental R
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> R.PersonFK
<span class="hljs-keyword">HAVING</span> COUNT(<span class="hljs-keyword">DISTINCT</span> R.BikeFK) = (
        <span class="hljs-keyword">SELECT</span> COUNT(*)
        <span class="hljs-keyword">FROM</span> Bike
    );
</code></pre>
<p>Say we want to find the people who have rented each and every bike registered in our database. To implement this, we’ll have to use the <strong>division</strong> operator, since in the query setup we will have two tables: one with tuples containing information about a person and a bike, indicating that the person has rented the bike, and another table with all the bikes registered in the system. If we apply a division operation from relational algebra on these tables, we can find all the people who appear in enough tuples in the first table to have rented all the bikes in the second table.</p>
<p>This can be implemented in many ways, and here we will focus on two. The first method involves <strong>counting</strong> how many different/distinct bikes each person has rented and checking if that number matches the total number of bikes in the system (we’ll see how to do this below). If it matches, then we know that person has rented all the bikes.</p>
<p>To do this, we can group the tuples in the <strong>Rental</strong> table by the foreign key PersonFK attribute, since we need to calculate how many bikes <strong>each person</strong> has rented. So we form groups of tuples representing the rentals of each person who has rented at least once (people who have never rented don’t appear in PersonFK of the Rental table).</p>
<p>Next, using the HAVING clause, we count how many different bikes each person has rented with <strong>COUNT(DISTINCT R.BikeFK)</strong>. This means that for each group of tuples, we count how many different values the BikeFK attribute takes in that group. This represents the number of different bikes rented, since BikeFK is the foreign key pointing to Bike and uniquely identifies the bike that has been rented.</p>
<p>Finally, we compare this number with the total number of bikes in our database, which we can get through a subquery using the aggregation function COUNT(*). Remember that we can use COUNT(*) without the GROUP BY clause being present in the subquery.</p>
<p>We can also approach the division of tables from a perspective closer to set theory. For example, below is the same query solved using NOT EXISTS and subqueries only:</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.PersonID
<span class="hljs-keyword">FROM</span> Person P
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> Bike B
        <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
                <span class="hljs-keyword">SELECT</span> *
                <span class="hljs-keyword">FROM</span> Rental R
                <span class="hljs-keyword">WHERE</span> R.PersonFK = P.PersonID
                    <span class="hljs-keyword">AND</span> R.BikeFK = B.BikeID
            )
    );
</code></pre>
<p>Here, if each person has rented every bike in the database, then there's not a bike that exists that they haven't rented. Let’s try to translate this concept into a SQL query literally: first, with a SELECT and FROM, we can <strong>“traverse”</strong> all the tuples of Person. Then for each one, we check that there is no bike the person hasn't rented. To do this, we construct a <strong>correlated subquery</strong> that returns all bikes that person hasn’t rented.</p>
<p>This subquery is simply constructed by "traversing" all the tuples of Bike and checking that there is no rental record between the person and the bike being traversed. We do this another correlated subquery that traverses the tuples of Rental and returns only those in which the person has rented the bike. If it doesn't return any tuples, then there were none with those characteristics, which tells us that the person traversed has never rented the bike traversed. In this case, we’re not interested in that person since they have not rented all the bikes in the database.</p>
<p>If someone really had rented them all, then the <strong>correlated subquery</strong> that traverses the tuples of <strong>Rental</strong> would always return at least one tuple. Then the the correlated subquery that traverses the tuples of Bike would never return tuples. And this would satisfy the NOT EXISTS condition that we imposed on the people.</p>
<p>If we read the SQL code we’ve implemented "literally," we’re <strong>traversing the people, and for each one we’re checking that they’ve rented every bike</strong>. So we finally get the same people as we do with the query that uses a grouping and a count of bikes rented by each person.</p>
<p>If we execute either of these queries, they probably won't return any results. After all, the probability of a person having rented each and every bike registered in the database is small.</p>
<p>But if we want to check whether the queries work or not, we can always manually insert tuples into <strong>Person</strong>, <strong>Bike</strong>, and <strong>Rental</strong>, especially in Rental. Then there would a person who has a tuple in Rental for each bike in the Bike table, and thus can be present in the result of the <strong>division</strong> operation.</p>
<p>Another query we can solve using a division operation from relational algebra is the one below. In it, we find all the people who have entered <strong>all</strong> the pools in a certain city (specifically the one with the CityID value of 55).</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> E.PersonFK
<span class="hljs-keyword">FROM</span> Entry E
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> CityPool CP <span class="hljs-keyword">ON</span> E.PoolFK = CP.PoolID
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Pool P <span class="hljs-keyword">ON</span> CP.PoolID = P.PoolID
<span class="hljs-keyword">WHERE</span> P.CityFK = <span class="hljs-number">55</span>
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> E.PersonFK
<span class="hljs-keyword">HAVING</span> COUNT(<span class="hljs-keyword">DISTINCT</span> E.PoolFK) = (
        <span class="hljs-keyword">SELECT</span> COUNT(*)
        <span class="hljs-keyword">FROM</span> CityPool CP2
            <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Pool P2 <span class="hljs-keyword">ON</span> CP2.PoolID = P2.PoolID
        <span class="hljs-keyword">WHERE</span> P2.CityFK = <span class="hljs-number">55</span>
    );
</code></pre>
<p>In this case, we first gather all the information from the Entry, CityPool, and Pool tables. This lets us get the information of the people who have entered the pools and the information of the city where the pool is located. So after gathering this information with the INNER JOIN operations, we impose the condition that the foreign key CityFK must reference a certain city, specifically the one identified with the value 55 in its primary key <strong>{CityID}</strong>. We do this to filter the resulting tuples from the JOINs, so that we only have those where people have entered pools in the specific city we are considering in the query.</p>
<p>But this condition doesn’t necessarily have to be in that WHERE clause, as there are other equally valid alternatives (using subqueries, CTE, and so on.).</p>
<p>Then we group the tuples by PersonFK, so that each group of tuples represents all the pool entries of a certain person (specifically entries in pools of the city identified by the value <strong>CityID=55)</strong>. To find only the people who have entered all the pools in that city, we use <strong>COUNT(DISTINCT E.PoolFK)</strong> to count the number of different pools they have entered. This equals the number of distinct values taken by the <strong>foreign key PoolFK</strong> in the <strong>Entry</strong> table. We then compare this number with the total number of city pools located in the city with CityID=55, all obtained through a simple uncorrelated subquery.</p>
<p>In this subquery, we perform another INNER JOIN between CityPool and Pool to gather data on all city pools with the foreign key CityFK that determines the city they are located in. This lets us declare the condition <strong>P2.CityFK = 55</strong> to count all the pools in that city using <strong>COUNT(*)</strong>. Also, the advantage of the subquery being uncorrelated is that it only needs to be computed once, since the number of pools in that city doesn't change while the query is running.</p>
<p>If we try to solve the previous query using the approach closest to set theory, as we did earlier, we will end up with an implementation that mainly uses the NOT EXISTS operator and correlated subqueries.</p>
<p>Conceptually, we can solve the query by going through all the people in the database and checking that there’s no city pool located in the city with <strong>CityID=55</strong> for which there is no entry associating the person with the pool. In other words, for each person, there must be an entry for every city pool in the city with <strong>CityID=55</strong>.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> * 
<span class="hljs-keyword">FROM</span> Person P
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> CityPool CP
            <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Pool PL <span class="hljs-keyword">ON</span> CP.PoolID = PL.PoolID
        <span class="hljs-keyword">WHERE</span> PL.CityFK = <span class="hljs-number">55</span>
            <span class="hljs-keyword">AND</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
                <span class="hljs-keyword">SELECT</span> *
                <span class="hljs-keyword">FROM</span> Entry E
                <span class="hljs-keyword">WHERE</span> E.PersonFK = P.PersonID
                    <span class="hljs-keyword">AND</span> E.PoolFK = CP.PoolID
            )
    );
</code></pre>
<p>Now, when coding all this, we arrive at a query very similar to the previous one where we looked for people who had rented all the bikes. As you can see, we first go through all the tuples of Person, and for each one, we construct a correlated subquery that gets all the city pools the corresponding person has not entered.</p>
<p>To do this, we perform a JOIN between CityPool and Pool and impose the condition that ensures all the city pools we consider are located in the city with CityID=55. Also, we verify with another correlated subquery that there is no entry of the person in the pool we are examining.</p>
<p>Each of these approaches to the same query have significant performance differences. In this last implementation, we nest several subqueries, leading to traversing many tuples, which is often unnecessary. On the other hand, using grouping tends to be faster since the traversal of tuples mainly depends on how the GROUP BY operation is implemented (which usually provides adequate performance for most queries).</p>
<p>Besides performance, in this last query, we can easily return all the information for each person because we directly use the Person table in the implementation. In contrast, in the previous approach using GROUP BY, we only returned each person's identifier, forcing us to use CTEs to perform a JOIN with the Person table if we want to return more information besides the identifier.</p>
<p>So when performing a division in SQL, we should consider not only the efficiency of the implementation but also the ease of modifying the query, as well as its clarity and maintainability.</p>
<p>The previous two queries were formulated considering the city with CityID=55, although this is an arbitrary decision. If we want to choose an appropriate value for <strong>CityID</strong> so that the two previous queries return data, since there may be cities where no person has entered all their pools, we can use the query below. For each person and city, it gets the number of pools in that city the person has entered, along with the total number of pools in that city.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> E.PersonFK,
    P.CityFK,
    COUNT(<span class="hljs-keyword">DISTINCT</span> E.PoolFK) <span class="hljs-keyword">AS</span> EnteredPools,
    (
        <span class="hljs-keyword">SELECT</span> COUNT(*)
        <span class="hljs-keyword">FROM</span> CityPool <span class="hljs-keyword">AS</span> CP2
            <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Pool <span class="hljs-keyword">AS</span> P2 <span class="hljs-keyword">ON</span> CP2.PoolID = P2.PoolID
        <span class="hljs-keyword">WHERE</span> P2.CityFK = P.CityFK
    ) <span class="hljs-keyword">AS</span> TotalPools
<span class="hljs-keyword">FROM</span> Entry <span class="hljs-keyword">AS</span> E
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> CityPool <span class="hljs-keyword">AS</span> CP <span class="hljs-keyword">ON</span> E.PoolFK = CP.PoolID
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Pool <span class="hljs-keyword">AS</span> P <span class="hljs-keyword">ON</span> CP.PoolID = P.PoolID
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> E.PersonFK, P.CityFK
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> EnteredPools, TotalPools;
</code></pre>
<p>As you can see, several JOIN operations are first performed to gather all the information from Entry, CityPool, and Pool, so we can later group the resulting tuples by PersonFK and CityFK. This means grouping the tuples into groups where each represents the entries a certain person has made in the pools of a certain city. Then, with <strong>COUNT(DISTINCT E.PoolFK)</strong>, we count the pools they have entered, since PoolFK is the foreign key in the Entry table that determines the pool the person has entered. Finally, with a correlated subquery in the SELECT, we get the total number of pools in the city identified by CityFK.</p>
<p>Finally, it's important to note that with this query, we will never get a value of 0 in the EnteredPools attribute. If a person has never entered any pool in a certain city, there will be no resulting tuples from these JOIN operations with <strong>(E.PersonFK, P.CityFK)</strong> attributes that reference both the person and the city.</p>
<p>This happens because no entry (Entry tuple) will have its foreign key PersonFK as the person and its foreign key PoolFK as a pool in the corresponding city that the person has visited (since they haven't visited any pool in that city).</p>
<p>So if we also want to include in our query's resulting table tuples with <strong>(E.PersonFK, P.CityFK)</strong> pairs of people who have never visited any pool in the city <strong>CityFK</strong>, we would need to use set operations to find those <strong>(E.PersonFK, P.CityFK)</strong> pairs and add the tuples constructed from these pairs to the final resulting table.</p>
<p>We can see another fundamental case we might encounter when implementing a division operation in SQL below. Here, we have a query where we get all the people who have or have had pool sanctions in all possible states.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> PS.PersonFK
<span class="hljs-keyword">FROM</span> PoolSanction PS
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Sanction S <span class="hljs-keyword">ON</span> PS.SanctionID = S.SanctionID
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> PS.PersonFK
<span class="hljs-keyword">HAVING</span> COUNT(<span class="hljs-keyword">DISTINCT</span> S.Status) = <span class="hljs-number">3</span>;
</code></pre>
<p>To implement this, we first perform a JOIN between <strong>PoolSanction</strong> and <strong>Sanction</strong>, ensuring with the first table that the sanction occurred in a pool and using the second table to get the sanction's state (which is stored in the Status attribute).</p>
<p>Then, as we need to count how many states each person has sanctions in, we group by the PersonFK attribute, creating groups of tuples that represent the sanctions each person has or has had. This way, we can use HAVING to require that the number of states in which a person has sanctions is equal to the total number of possible states a sanction can have.</p>
<p>On one hand, with <strong>COUNT(DISTINCT S.Status)</strong>, we can count how many different values the Status attribute takes in each group – or in other words, the number of states of the sanctions associated with a person. And, since there are three possible states ('created', 'active', 'expired'), we simply compare the resulting count from the aggregation function with 3.</p>
<p>But if we use the constant 3 in the comparison and later modify the database to include more or fewer states in the sanctions, we will be forced to change that number. This makes the query not as maintainable as it could be.</p>
<p>So another another option we have for declaring the condition in the HAVING clause is to compare the result of the aggregation function COUNT(*) with the result of a subquery that calculates how many possible states a sanction can have.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> PS.PersonFK
<span class="hljs-keyword">FROM</span> PoolSanction PS
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Sanction S <span class="hljs-keyword">ON</span> PS.SanctionID = S.SanctionID
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> PS.PersonFK
<span class="hljs-keyword">HAVING</span> COUNT(<span class="hljs-keyword">DISTINCT</span> S.Status) = (<span class="hljs-keyword">SELECT</span> COUNT(<span class="hljs-keyword">DISTINCT</span> Status) <span class="hljs-keyword">FROM</span> Sanction);
</code></pre>
<p>As up can see above, this subquery is non-correlated, as it simply counts how many <strong>distinct values</strong> the <strong>Status</strong> attribute takes in the <strong>Sanction</strong> table. But implementing the query this way has a problem: we’re assuming that in the Sanction table, specifically in the Status attribute, we can find all the possible values that Status can take. But this might not be the case, as if the table is empty, no distinct values can be counted in the Status attribute.</p>
<p>This means that this last implementation of the query only works when the <strong>Sanction</strong> table contains tuples representing sanctions where there is at least one sanction in all possible states. If we can guarantee that the database meets this condition, then the above implementation is more convenient for us because it requires no maintenance.</p>
<p>But this condition is not usually met, so it’s not a good practice to assume that we’ll find all possible values an attribute can take in that attribute. For example, if we think of an <strong>integer</strong> attribute, it’s clear that there don’t have to be tuples that take a different value for every possible value the attribute can have.</p>
<p>Another option we have is to skip grouping and use a set theory-based approach. As you can see, in the implementation above, we go through all the tuples of Person, and for each one, we check that there <strong>exists</strong> a pool sanction with the status <strong>‘created’</strong>. Also, using the logical operator AND, we require that at the same time there exists another pool sanction with the status <strong>‘active’</strong>. Finally, we use another logical operator AND to also require that for that person there exists another pool sanction in the status <strong>‘expired’</strong>.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> p.PersonID
<span class="hljs-keyword">FROM</span> Person p
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> PoolSanction ps
            <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Sanction s <span class="hljs-keyword">ON</span> ps.SanctionID = s.SanctionID
        <span class="hljs-keyword">WHERE</span> ps.PersonFK = p.PersonID
            <span class="hljs-keyword">AND</span> s.Status = <span class="hljs-string">'created'</span>
    )
    <span class="hljs-keyword">AND</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> PoolSanction ps
            <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Sanction s <span class="hljs-keyword">ON</span> ps.SanctionID = s.SanctionID
        <span class="hljs-keyword">WHERE</span> ps.PersonFK = p.PersonID
            <span class="hljs-keyword">AND</span> s.Status = <span class="hljs-string">'active'</span>
    )
    <span class="hljs-keyword">AND</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> PoolSanction ps
            <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Sanction s <span class="hljs-keyword">ON</span> ps.SanctionID = s.SanctionID
        <span class="hljs-keyword">WHERE</span> ps.PersonFK = p.PersonID
            <span class="hljs-keyword">AND</span> s.Status = <span class="hljs-string">'expired'</span>
    );
</code></pre>
<p>As you can see above, this implementation is equivalent to the previous one where we used groupings and counts to implement the division operation. But this approach is clearly less maintainable, though possibly easier to understand in some aspects.</p>
<p>For example, in this implementation, the names of the different <strong>Status</strong> values appear explicitly in the conditions we impose in each correlated subquery, which is generally not a good practice. If you want to modify the database domain, you will also have to modify these values.</p>
<p>Also, we’re duplicating the same code multiple times, making the query code as a whole less maintainable. This is because if the query itself needs to be modified, it’s very likely that we’ll need to make changes in all three subqueries, slowing down the management process.</p>
<p>So although the set theory-based approach may be impractical in certain situations, it can work for a small database like the one we're dealing with here. But, whenever possible, it's best to choose solutions that are more maintainable and require fewer changes in the future.</p>
<p>In this specific case, the best option would be to use the grouping approach where the number of sanction statuses for a person is compared with the total number of statuses, as changing that number in the query is easier than modifying the code of several subqueries. This also avoids having to make assumptions about the <strong>Sanction</strong> tuples.</p>
<p>Let’s look at another query that’s similar to the previous ones, where we can see a different way the division operator can appear. It retrieves all the people who, for every city they have lived in, have visited at least one pool located in that city.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> P.PersonID
<span class="hljs-keyword">FROM</span> Person P
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> Residence R
        <span class="hljs-keyword">WHERE</span> R.PersonFK = P.PersonID
            <span class="hljs-keyword">AND</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
                <span class="hljs-keyword">SELECT</span> *
                <span class="hljs-keyword">FROM</span> Entry E
                    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> Pool PO <span class="hljs-keyword">ON</span> E.PoolFK = PO.PoolID
                <span class="hljs-keyword">WHERE</span> E.PersonFK = P.PersonID
                    <span class="hljs-keyword">AND</span> PO.CityFK = R.CityFK
            )
    );
</code></pre>
<p>For each person, keep them only if there is no residence of theirs that lacks a matching pool-visit in the same city. Equivalently: for every city a person has lived in (from Residence), there must be at least one record showing they visited a pool in that city.</p>
<p>The implementation of this approach is very similar to how we express it in natural language. On one hand, we go through the tuples of Person with a SELECT and a FROM, and we set the condition that the result of a subquery is empty using NOT EXISTS.</p>
<p>In this correlated subquery, we go through the tuples of Residence for the person we are currently checking the condition for, so to keep only the residences we are interested in, we impose the condition <strong>R.PersonFK = P.PersonID</strong> in the subquery. This ensures that the selected Residence tuples have their foreign key PersonFK pointing to the person we are going through, whose identification is given by <strong>P.PersonID</strong>.</p>
<p>On the other hand, within this subquery, we also check that another correlated and nested subquery doesn’t return any tuples either. This last subquery is dedicated to getting all the entries where the person identified by <strong>P.PersonID</strong> has entered a pool located in the city identified by <strong>R.CityFK</strong> – that is, the city of the residence we are going through at the time of executing this subquery.</p>
<p>In summary, in this query, we have seen that divisions don’t always refer to situations where the tuples we want to obtain are "associated" with all the tuples of another table. Instead, as in this case, they can also refer to the output tuples of our query needing to meet a certain condition in relation to all the tuples of another table.</p>
<p>Similar to the previous query, we can consider another one where we need to find people who have or have had at least one travel booking in all existing cruise classes.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> CB.PersonFK
<span class="hljs-keyword">FROM</span> CruiseBooking CB
    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> CruiseShip CS <span class="hljs-keyword">ON</span> CB.ShipFK = CS.ShipID
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> CB.PersonFK
<span class="hljs-keyword">HAVING</span> COUNT(<span class="hljs-keyword">DISTINCT</span> CS.<span class="hljs-keyword">Class</span>) = (
        <span class="hljs-keyword">SELECT</span> COUNT(<span class="hljs-keyword">DISTINCT</span> <span class="hljs-keyword">Class</span>)
        <span class="hljs-keyword">FROM</span> CruiseShip
    );
</code></pre>
<p>In this case, we start by setting up the division operation through grouping and counting. First, we perform an INNER JOIN between the <strong>CruiseBooking</strong> and <strong>CruiseShip</strong> tables. This allows us to gather information about the person who made each travel booking using the foreign key <strong>PersonFK</strong> from CruiseBooking and the information about the cruise class for the trip. This same table has a foreign key <strong>ShipFK</strong> that uniquely identifies the cruise ship for the trip, from which we can determine its class.</p>
<p>So after this operation, we group by the PersonFK attribute, as we’ll need to count how many different cruise classes each person has booked to perform the division.</p>
<p>Regarding this quantity, we calculate it using the aggregation function <strong>COUNT(DISTINCT CS.Class)</strong>, which is executed once for each group of tuples. Then we compare it with the total number of cruise classes in our database.</p>
<p>In this case, we could have directly written the number instead of using an uncorrelated subquery to get the total number of classes by looking at the distinct values of the <strong>Class</strong> attribute from the <strong>CruiseShip</strong> table. So as it stands, with the subquery, we’re implicitly assuming that the CruiseShip table contains cruises in all existing classes (but this may not be the case).</p>
<p>Imagine if the table is empty, for example – the subquery would result in a total of 0 cruise classes, when in reality, there may be more (the domain of the Class attribute may contain more values than those actually appearing in the table).</p>
<p>But it’s important to clarify here that by “all cruise classes” we mean all possible values that the <strong>Status</strong> attribute can take – that is, the values we define as the domain of the attribute. On the other hand, in some circumstances, we can assume that all cruise classes correspond to the distinct values that the Status attribute takes in the <strong>CruiseShip</strong> table, all depending on the domain we are working with.</p>
<p>For simplicity, from now on in this domain, we’ll assume that the distinct values of an attribute like <strong>Class</strong> found in its corresponding table are equivalent to all the values it can take. If we think about it, this makes sense because if there are only 2 distinct values in the Class attribute of the CruiseShip table, then all the bookings made throughout the time the database has existed will have to reference some cruise in the CruiseShip table (whose Class will have one of those two values). There might be no bookings referencing cruises of a certain class, but if there are cruises of two classes, then it makes sense to assume that those two classes make up <strong>“all the classes the Class attribute can hold.”</strong></p>
<p>So, by assuming that the Class attribute of the CruiseShip table contains "all the classes" of cruises, we can solve the query using a set theory approach as shown in the query below.</p>
<p>Here, we first go through all the tuples in CruiseBooking that represent bookings. In each one, we check that there is no cruise (of any class, rather) for which no booking has been made by the person referenced by the foreign key PersonFK of the CruiseBooking tuple we are examining.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> <span class="hljs-keyword">DISTINCT</span> CB.PersonFK
<span class="hljs-keyword">FROM</span> CruiseBooking CB
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> CruiseShip C
        <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
                <span class="hljs-keyword">SELECT</span> *
                <span class="hljs-keyword">FROM</span> CruiseBooking CB2
                    <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> CruiseShip CS2 <span class="hljs-keyword">ON</span> CB2.ShipFK = CS2.ShipID
                <span class="hljs-keyword">WHERE</span> CB2.PersonFK = CB.PersonFK
                    <span class="hljs-keyword">AND</span> CS2.<span class="hljs-keyword">Class</span> = C.<span class="hljs-keyword">Class</span>
            )
    );
</code></pre>
<p>That is, since we are only interested in getting the people who have ever booked, we start the query by going through CruiseBooking, not Person, because there may be people in Person who have never booked.</p>
<p>So to check that there is no cruise with these characteristics, we use the NOT EXISTS operator and a correlated subquery in which we go through all the cruises registered in the CruiseShip table. For each one, we check that there is no travel booking where the cruise is the one <strong>whose class is the same</strong> as the cruise and person we are currently examining in the query.</p>
<p>By doing this, we ensure that for all the people returned by our query, there is no cruise of any class that hasn’t been booked at least once by that person. But we can do this correctly only if we are sure that the Class attribute in CruiseShip includes what we consider as <strong>“all possible cruise classes“</strong>. If we didn't have this assurance, then this set theory approach would not be correct, because the correlated subquery that goes through the tuples of CruiseShip might not be covering all possible cruise classes.</p>
<p>For example, imagine the CruiseShip table is empty. In that case, this approach would return more people than it should, since that subquery would never return tuples.</p>
<p>On the contrary, in the other approach based on groupings, if the CruiseShip table is empty, then the uncorrelated subquery that counts the total number of classes would return 0. Also, the HAVING condition would never be met, preventing the return of people who do not meet the condition defined in the query statement.</p>
<p>So as you can see, it’s not always better to use just one approach based on either <strong>groupings</strong> or <strong>set theory</strong> – it varies depending on the situation.</p>
<p>In this specific case, it’s more practical to use groupings – mainly for efficiency (since internally a grouping is usually faster than executing a correlated subquery multiple times) but also for simplicity of maintenance and code clarity.</p>
<p>To wrap up our discussion on the division operator of relational algebra, it’s important to note that there are times when we have to do division using intermediate tables (CTE) instead of tables from the database itself.</p>
<p>For example, in the query below, we obtain the ships that have made at least one trip departing from and arriving at each pair of cities with an area of at most 11 km². In other words, all ships that have made at least one trip between each pair of cities with this characteristic.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> AllPairs <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> C1.CityID <span class="hljs-keyword">AS</span> Dep, C2.CityID <span class="hljs-keyword">AS</span> Arr
    <span class="hljs-keyword">FROM</span> City C1 <span class="hljs-keyword">CROSS</span> <span class="hljs-keyword">JOIN</span> City C2
    <span class="hljs-keyword">WHERE</span> C1.CityID &lt;&gt; C2.CityID <span class="hljs-keyword">AND</span> C1.Area&lt;<span class="hljs-number">11</span> <span class="hljs-keyword">AND</span> C2.Area&lt;<span class="hljs-number">11</span>
),
ShipVisits <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> V.ShipFK,
        V.DepartureCityFK <span class="hljs-keyword">AS</span> Dep,
        V.ArrivalCityFK <span class="hljs-keyword">AS</span> Arr
    <span class="hljs-keyword">FROM</span> Voyage V
        <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> City C1 <span class="hljs-keyword">ON</span> V.DepartureCityFK = C1.CityID
        <span class="hljs-keyword">INNER</span> <span class="hljs-keyword">JOIN</span> City C2 <span class="hljs-keyword">ON</span> V.ArrivalCityFK = C2.CityID
    <span class="hljs-keyword">WHERE</span> C1.Area&lt;<span class="hljs-number">11</span> <span class="hljs-keyword">AND</span> C2.Area&lt;<span class="hljs-number">11</span>
)
<span class="hljs-keyword">SELECT</span> SV.ShipFK
<span class="hljs-keyword">FROM</span> ShipVisits SV
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> SV.ShipFK
<span class="hljs-keyword">HAVING</span> COUNT(<span class="hljs-keyword">DISTINCT</span> (SV.Dep, SV.Arr)) = (
        <span class="hljs-keyword">SELECT</span> COUNT(*)
        <span class="hljs-keyword">FROM</span> AllPairs
    );
</code></pre>
<p>As you can see in the implementation, to make the code simpler, we can first build an intermediate table with all possible pairs of cities with an area value <strong>&lt;11</strong>. We. cando this by executing a <strong>CROSS JOIN</strong> between the <strong>City</strong> table and itself, as it contains all the cities registered in our database. Then we require that both cities in the pair have an area &lt;11.</p>
<p>It’s important to note that the <strong>Area</strong> attribute of the City table contains values representing square kilometers, so it’s straightforward to declare the &lt;11 condition in our query. But if this attribute had values in other units, we’d need to adapt to them or convert them to other units that we could easily work with. It’s crucial to consider the units in which the values we compare are measured to correctly code the query.</p>
<p>Finally, this table includes all possible pairs of cities that meet the area characteristic, meaning it doesn't matter if the same pair of cities <strong>(A,B)</strong> also appears in the table as <strong>(B,A)</strong>.</p>
<p>Then, we build another intermediate table where we store the different pairs of cities each cruise has visited throughout all its trips, considering only those cities that meet the query conditions (area &lt;11).</p>
<p>To do this, we simply extract the foreign key attributes ShipFK, DepartureCityFK, and ArrivalCityFK. These determine the cruise that made the trip and the departure and arrival cities of the trip from the resulting table of the INNER JOIN operations between the <strong>Voyage</strong> table and the City table itself.</p>
<p>We perform these operations to access the area information of each city, allowing us to impose the same area conditions as in the first intermediate table <strong>AllPairs</strong>. If we didn't do this, we might consider cruise trips between cities that don't meet the conditions we are looking for. This would increase the number of <strong>“valid”</strong> city pairs the cruise has traveled between. Since we’re going to structure the query using a grouping and a <strong>count</strong>, it’s essential not to count irrelevant elements for our query.</p>
<p>Once both CTEs are built, we perform a grouping on the <strong>ShipVisits</strong> tables based on the <strong>ShipFK</strong> attribute. We do this to calculate, for each cruise, the number of distinct pairs of cities it has traveled between. We easily calculate this using the aggregation function <strong>COUNT(DISTINCT (SV.Dep, SV.Arr))</strong>. Then we can compare the returned value with the total number of city pairs that exist and that we have stored in the first CTE called <strong>AllPairs</strong>, all within the HAVING clause.</p>
<p>To keep only those cruises that have traveled through every pair of cities calculated in AllPairs, we compare the output of the <strong>COUNT()</strong> aggregation function with the result of an uncorrelated subquery that simply counts how many tuples the intermediate table <strong>AllPairs</strong> has.</p>
<p>In the total count of pairs, we don’t have to use the <strong>DISTINCT</strong> modifier, since the CROSS JOIN never generates repeated city pairs given the very definition of the cross product operation. And there there are no identical tuples in the City table, meaning there are no identical cities in our database (much less with the same value of their primary key <strong>CityID</strong>). But if we wanted to use the DISTINCT modifier to count how many distinct tuples are in AllPairs, we could use the syntax <strong>COUNT(DISTINCT AllPairs.*)</strong>.</p>
<p>Regarding this last subquery, we could have avoided explicitly constructing all the city pairs in <strong>AllPairs</strong> if we had directly performed the same computation as in <strong>AllPairs</strong> – but returning only <strong>COUNT(*)</strong>. This would directly count all the city pairs with the characteristics we are looking for. But we can only do this if we code the query using grouping and counting, as we’ll see that it can also be implemented based on set operations, for which we’ll necessarily need to construct and store the pairs in <strong>AllPairs</strong>.</p>
<p>So just as we have shown with other queries, we can also approach this one using <strong>set theory operators</strong>. As you can see below, the intermediate tables are constructed in the same way except for <strong>ShipVisits</strong>, where we don't need the cities involved in the trips to meet the condition of having an area &lt;11.</p>
<p>This is because those ShipVisits tuples will later be compared with the city pairs in AllPairs, which do meet the condition. This way, we end up with cruises that have made a trip in all the pairs of AllPairs, regardless of additional tuples in ShipVisits with trips between cities that don't meet the condition we're looking for.</p>
<p>Although this isn't crucial for resolving the query, it's important to note that ShipVisits contains more tuples than necessary, which might slow down the query since <strong>ShipVisits</strong> will later be used in a <strong>correlated subquery</strong>, resulting in multiple scans of its tuples.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> AllPairs <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> C1.CityID <span class="hljs-keyword">AS</span> Dep, C2.CityID <span class="hljs-keyword">AS</span> Arr
    <span class="hljs-keyword">FROM</span> City C1 <span class="hljs-keyword">CROSS</span> <span class="hljs-keyword">JOIN</span> City C2
    <span class="hljs-keyword">WHERE</span> C1.CityID &lt;&gt; C2.CityID <span class="hljs-keyword">AND</span> C1.Area&lt;<span class="hljs-number">11</span> <span class="hljs-keyword">AND</span> C2.Area&lt;<span class="hljs-number">11</span>
),
ShipVisits <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> V.ShipFK,
        V.DepartureCityFK <span class="hljs-keyword">AS</span> Dep,
        V.ArrivalCityFK <span class="hljs-keyword">AS</span> Arr
    <span class="hljs-keyword">FROM</span> Voyage V
)
<span class="hljs-keyword">SELECT</span> SV.ShipFK
<span class="hljs-keyword">FROM</span> ShipVisits SV
<span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
        <span class="hljs-keyword">SELECT</span> *
        <span class="hljs-keyword">FROM</span> AllPairs AP
        <span class="hljs-keyword">WHERE</span> <span class="hljs-keyword">NOT</span> <span class="hljs-keyword">EXISTS</span> (
                <span class="hljs-keyword">SELECT</span> *
                <span class="hljs-keyword">FROM</span> ShipVisits SV2
                <span class="hljs-keyword">WHERE</span> SV2.ShipFK = SV.ShipFK
                    <span class="hljs-keyword">AND</span> SV.Dep = AP.Dep
                    <span class="hljs-keyword">AND</span> SV.Arr = AP.Arr
            )
    );
</code></pre>
<p>After constructing the CTEs, we solve the query in a way similar to the other divisions we've seen. First, we go through the tuples of ShipVisits (although we could also choose to go through those of CruiseShip, since what we want is to go through all the cruises in the database, or at least those that have made a trip). So instead of using CruiseShip, which might contain cruises that have never made a trip, we choose to go through the tuples of ShipVisits, where we can find cruises referenced by the <strong>foreign key ShipFK</strong> from the <strong>Voyage</strong> table, which we know have made at least one trip.</p>
<p>In each of these tuples, we check that there is no pair of cities from AllPairs for which there is no trip made by the cruise we are currently going through between the cities of that pair.</p>
<p>To do this, we use the NOT EXISTS operator and two nested correlated subqueries. In the first, we go through the tuples of AllPairs – that is, the pairs of cities that do meet the condition of having an area &lt;11. Then for each pair, we use NOT EXISTS again on another correlated subquery that gets all the trips made by the cruise currently being processed in the query execution over the cities of the corresponding pair from AllPairs.</p>
<p>In a more intuitive way, we’re getting all the cruises for which there is no pair of cities from AllPairs where the cruise hasn't traveled at least once. As you can guess, since the cities in AllPairs do meet the condition of having an area less than 11 km², it doesn't matter that ShipVisits has trips with cities that don't meet this condition – because in the query we check that for a certain pair of cities from <strong>AllPairs</strong> there is no trip of a cruise in those cities. So it’s really indifferent which cities are present in the trips of ShipVisits, as those that meet the condition will definitely be there since we don't impose any condition when constructing that intermediate table.</p>
<p>In summary, with this approach, we can solve the query just as we did before using groupings and counts. But the difference here is that we can save the conditions (area &lt;11) that we imposed when constructing the tuples of ShipVisits.</p>
<p>At first glance, this might seem like an improvement in code clarity, as it’s shorter. This makes it more maintainable in this case because fewer operations and statements are needed to construct the CTE. But the resulting CTE contains more tuples, specifically those that represent all the trips each cruise has made, not just those made between cities that meet the condition of having an area &lt;11.</p>
<p>This additional number of tuples impacts the computation of the query. But to analyze this impact, we must also consider that in constructing ShipVisits, we are saving two JOIN operations, which are highly costly, in addition to the expected amount of data with which the query will be executed.</p>
<p>For example, if the amount of data in the involved tables is small, the performance difference won’t be significantly noticeable. But if it’s large, it’s more beneficial to have the smallest possible number of tuples in ShipVisits, even if it requires performing an additional JOIN.</p>
<p>This is because the correlated subquery that goes through the tuples of ShipVisits is executed once for each tuple of AllPairs, and all of this is executed once for each tuple of ShipVisits (we could have replaced this last one with CruiseShip to improve performance, as the number of cruises is fixed and tends to be smaller than the number of trips).</p>
<p>So the computation involved in going through all the tuples of ShipVisits is much greater than the computation of a simple JOIN used to construct the CTE itself – which, despite being computationally costly, only needs to be executed once (not multiple times depending on the number of tuples in other tables).</p>
<p>To finish with the division operation, we've seen that we can implement it in SQL using the <strong>EXISTS</strong> operator (either as is or negated with the logical NOT operator) and a correlated subquery. In it, the SELECT statement uses the * notation to return all the attributes of the corresponding table. This means that to check if the subquery returns any tuple or not, we construct its result so that each tuple possibly has multiple attributes – meaning all those that result from using the <strong>SELECT *</strong> notation. But sometimes instead of returning several attributes, it simply returns a column with a fixed value like the integer 1.</p>
<p>In general, using the SELECT * notation in a correlated subquery to which the EXISTS operator is applied is considered good practice, so it’s coded this way by default. But there are also other possibilities like <strong>SELECT 1</strong>, which at first glance might seem more efficient because it doesn't return unnecessary attributes since it only checks if the subquery results in any tuple or not.</p>
<p>In summary, the decision on which attributes to return in a correlated subquery using the EXISTS operator is mainly determined by the characteristics of the DBMS, as each <a target="_blank" href="https://dba.stackexchange.com/questions/159413/exists-select-1-vs-exists-select-one-or-the-other">implementation</a> of the <a target="_blank" href="https://stackoverflow.com/questions/424212/performance-of-sql-exists-usage-variants">DBMS</a> handles these operations differently at the physical level.</p>
<h3 id="heading-ranking-queries">Ranking Queries</h3>
<p>To conclude with the different "types" of queries we might encounter, there are queries where we need to calculate a <strong>ranking</strong> – that is, ordering elements based on the value they have for a certain metric. For example, ordering people by the number of bike rentals they have made, allowing us to find out who has made the most or fewest rentals, among many other similar tasks.</p>
<p>In this case, these approaches don’t have any equivalent operator in relational algebra. This is because the calculation of rankings is based on the combination of multiple techniques and tools like groupings, aggregations, or uncorrelated subqueries that aren’t present in relational algebra as specific operators.</p>
<p>This is mainly because in relational algebra, there is no concept of order, and since tables are treated as sets of tuples, there is no unique way to number the tuples positionally to establish an <strong>internal order of the set</strong>. In other words, within a set, its elements don’t necessarily have an order among them unless we explicitly define it.</p>
<p>We can start by finding the maximum value of whatever we’re ranking for (and, optionally, where in the table this occurs). For example, in the query below, we get the maximum passenger capacity among all the cruise ships in the CruiseShip table.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> MAX(PassengerCapacity) <span class="hljs-keyword">AS</span> MaxCapacity
<span class="hljs-keyword">FROM</span> CruiseShip;
</code></pre>
<p>In terms of approach, solving this query involves establishing a ranking of the cruise ships based on their passenger capacity (this is their metric). The one with the highest capacity occupies the first place in the ranking, followed by the other cruise ships. So if we take the first in the ranking and access its metric, we will have the maximum passenger capacity, which is what we want to obtain.</p>
<p>In SQL, implementing this query is very simple if we only want to get the metric value and its values are already calculated in an attribute. As you can see, we simply use the <strong>MAX()</strong> aggregation function, which we give the attribute where the metric values are calculated as an input argument. Finally, when we execute the query, we will see that only one tuple is returned with that maximum value in the attribute we have named with the alias <strong>MaxCapacity</strong>.</p>
<p>But the implementation is not always that simple. For example, if we want to get not only the maximum value of the metric but also the specific element associated with that metric – in this case, the cruise ship with the highest passenger capacity – we first need to go through the tuples in CruiseShip and check each one to see if it corresponds to the cruise ship with the highest passenger capacity.</p>
<p>Specifically, what we check in each tuple is whether the passenger count is equal to the maximum or not, so that we only keep those tuples where the <strong>PassengerCapacity</strong> value is exactly equal to the maximum value of that attribute.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> ShipID, PassengerCapacity
<span class="hljs-keyword">FROM</span> CruiseShip
<span class="hljs-keyword">WHERE</span> PassengerCapacity = (
    <span class="hljs-keyword">SELECT</span> MAX(PassengerCapacity)
    <span class="hljs-keyword">FROM</span> CruiseShip
);
</code></pre>
<p>This is reflected in the query code above. In the WHERE clause, we check that the PassengerCapacity attribute value is equal to the result of the uncorrelated subquery that returns its maximum value. We use the MAX() aggregation function for this just like before.</p>
<p>If the values match, we will have found the tuple of the cruise ship with the highest passenger capacity. But there may be several cruise ships with that same capacity, so our query will return them as well.</p>
<p>If we want to get only one cruise ship, we have the option to add an additional clause <strong>LIMIT 1</strong> at the very end of the query, which basically returns only the first tuple of the resulting table from the query.</p>
<p>This <a target="_blank" href="https://www.datacamp.com/tutorial/sql-limit">LIMIT clause</a>, it’s not part of the <a target="_blank" href="https://www.contrib.andrew.cmu.edu/~shadow/sql/sql1992.txt">SQL-92 standard</a>, but it can still be used in any query we need as long as the DBMS supports it (all <strong>modern</strong> DBMSs support it). Its use is simple: we just give it a number that indicates the number of tuples from the resulting table of the query that we want to get from the first tuple located at the top of the table, ignoring the rest.</p>
<p>Another option we have is to do without the MAX() aggregation function. As you can see below, most of the query code is the same, except for the subquery. Instead of returning the maximum value of the PassengerCapacity attribute, it returns the attribute itself – meaning all the values in its corresponding column in the CruiseShip table.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> ShipID, PassengerCapacity
<span class="hljs-keyword">FROM</span> CruiseShip
<span class="hljs-keyword">WHERE</span> PassengerCapacity &gt;= <span class="hljs-keyword">ALL</span> (
    <span class="hljs-keyword">SELECT</span> PassengerCapacity
    <span class="hljs-keyword">FROM</span> CruiseShip
);
</code></pre>
<p>In this way, the condition of the WHERE clause uses the operator &gt;= along with the ALL modifier, which establishes that, for a certain tuple of CruiseShip, its PassengerCapacity value must be greater than all the values returned by the subquery. Or put another way, our query retrieves information on all cruise ships whose passenger capacity is greater than or equal to each and every capacity stored in the PassengerCapacity attribute of the CruiseShip table.</p>
<p>Specifically, here we have to use the operator <strong>&gt;=,</strong> not <strong>&gt;</strong>, because if we are going through the tuple of a cruise ship that does have the highest passenger capacity, its capacity will at most be equal to the maximum capacity of the CruiseShip table (but never greater). That is, if the maximum is a value <strong>X</strong>, then there will be no cruise ship with a capacity <strong>&gt;X</strong>, but there will be one or more with a capacity <strong>\=X</strong>, which are the ones we want to find.</p>
<p>At the same time, these have a capacity X that is greater than the rest of the capacities of the other cruise ships, which is why we use the operator <strong>&gt;=</strong>.</p>
<p>The <strong>ALL</strong> modifier is necessary to ensure that the value of the PassengerCapacity attribute meets the condition imposed by the &gt;= operator with respect to each and every tuple returned by the subquery. In this case, it only returns tuples with an attribute or column with the values of all the passenger capacities that it must be compared with.</p>
<p>As you can guess, even though this way of implementing the query is equivalent to the previous one, here the subquery returns a series of values that are compared for each tuple of CruiseShip. That is, for each cruise ship, all the tuples of the subquery are traversed to perform the comparison declared in the <strong>WHERE</strong> clause. This requires much more computation than simply comparing with a number like the maximum capacity obtained from the MAX() function.</p>
<p>So since the <strong>subquery</strong> is <strong>non-correlated</strong> and is computed only once, it’s more optimal to use the previous approach where we used MAX() than this one, as this approach uses more space to store the subquery tuples and more time unnecessarily traversing them to make the comparisons.</p>
<p>Continuing with queries where we need to calculate a <strong>maximum</strong>, here we have another one where we get the person (or people) who have had the most residences in cities, along with that maximum number of residences.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> R.PersonFK <span class="hljs-keyword">AS</span> PersonID, COUNT(*) <span class="hljs-keyword">AS</span> NumResidences
<span class="hljs-keyword">FROM</span> Residence <span class="hljs-keyword">AS</span> R
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> R.PersonFK
<span class="hljs-keyword">HAVING</span> COUNT(*) &gt;= <span class="hljs-keyword">ALL</span> (
        <span class="hljs-keyword">SELECT</span> COUNT(*)
        <span class="hljs-keyword">FROM</span> Residence
        <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> PersonFK
    );
</code></pre>
<p>We can find the information to solve this query in the <strong>Residence</strong> table – specifically in the tuples themselves, where each one represents a residence. The person is referenced by the foreign key <strong>PersonFK</strong> and the city where the person has lived is referenced by the foreign key <strong>CityFK</strong>.</p>
<p>So, in this table, we don't have a number in an attribute that tells us the number of residences a person has had. Instead, the tuples themselves represent the residences of the people, and we need to count them to know which person has or has had the most residences.</p>
<p>To do this, we can group the tuples in Residence by the attribute PersonFK, since we need to count residences for each person. In this way, we form groups of tuples that represent all the residences a person has had.</p>
<p>Once the groups are made, we can use <strong>COUNT(*)</strong> to count how many residences the "representative" person of that group of tuples has or has had. Then, to ensure that this number is the maximum, we use the operator &gt;= along with the ALL modifier and a subquery.</p>
<p>In this case, the subquery calculates, for each person, the total number of residences they have or have had in the same way as in the main query, using a grouping by the PersonFK attribute of Residence and the aggregation function COUNT(*).</p>
<p>With this, we can verify, in the <strong>HAVING</strong> clause, that the number of residences of a certain person is greater than or equal to all the numbers of residences that all the people present in the Residence table have or have had.</p>
<p>On the other hand, we could try to implement the query without using the <strong>\&gt;=</strong> operator and the ALL modifier, and instead use only a non-correlated subquery and the aggregation function MAX().</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span>
  R.PersonFK   <span class="hljs-keyword">AS</span> PersonID,
  COUNT(*)     <span class="hljs-keyword">AS</span> NumResidences
<span class="hljs-keyword">FROM</span> Residence <span class="hljs-keyword">AS</span> R
<span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> R.PersonFK
<span class="hljs-keyword">HAVING</span> COUNT(*) = (
  <span class="hljs-keyword">SELECT</span> MAX(COUNT(*))
  <span class="hljs-keyword">FROM</span> Residence
  <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> PersonFK
);
</code></pre>
<p>As you can see above, the query construction is very similar, except that in the HAVING clause, we directly compare COUNT(*), which returns the number of residences a person has or has had with the result of the subquery, which seems to obtain the maximum number of residences any person has had.</p>
<p>But if we look at the SELECT clause of the subquery, several nested aggregation functions like <strong>MAX(COUNT(*))</strong> appear, intending to calculate the maximum value of the numbers of residences people have had. But <strong>this is not allowed in SQL</strong>. In fact, if we run the query, the DBMS will give us an error because <strong>an aggregation function can’t be used as an input argument to another aggregation function</strong>.</p>
<p>If we really want to use the aggregation function MAX() to solve the query, we have no choice but to first build a CTE where we store all the people who have ever had a residence and their respective number of residences.</p>
<p>You can see this in the code below, and it’s very similar to the approach we followed before to solve the query. This involves grouping the residence tuples by their foreign key attribute <strong>PersonFK</strong> and using <strong>COUNT(*)</strong> to count how many tuples each group has, that is, how many residences each person has.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">WITH</span> ResCount <span class="hljs-keyword">AS</span> (
    <span class="hljs-keyword">SELECT</span> PersonFK <span class="hljs-keyword">AS</span> PersonID, COUNT(*) <span class="hljs-keyword">AS</span> NumResidences
    <span class="hljs-keyword">FROM</span> Residence
    <span class="hljs-keyword">GROUP</span> <span class="hljs-keyword">BY</span> PersonFK
)
<span class="hljs-keyword">SELECT</span> RC.PersonID,
    RC.NumResidences
<span class="hljs-keyword">FROM</span> ResCount RC
<span class="hljs-keyword">WHERE</span> RC.NumResidences = (
        <span class="hljs-keyword">SELECT</span> MAX(NumResidences)
        <span class="hljs-keyword">FROM</span> ResCount
    );
</code></pre>
<p>Then, once this intermediate table <strong>ResCount</strong> is built, we are in the same situation as in the queries at the beginning of this section, where the numbers of residences are now values stored in an attribute.</p>
<p>So we can follow the usual approach to get the tuple or tuples from ResCount with the maximum value in their attribute <strong>NumResidences</strong>. This involves going through all its tuples and checking if their NumResidences value matches the maximum. We can easily calculate this with a non-correlated subquery and the aggregation function MAX().</p>
<p>After these queries, we can consider solving them by obtaining the element with the lowest value in its metric in the ranking.</p>
<p>For example, in this last case, it would correspond to finding the person or people who have had the fewest residences (which doesn't make much sense in this query, but it does in others).</p>
<p>So, to calculate <strong>minimums</strong> instead of <strong>maximums</strong> in SQL, you use exactly the same constructions we just saw, with the difference that the operators and aggregation functions used change, such as the operator &gt;= to &lt;= and the aggregation function MIN() is used instead of MAX().</p>
<p>In addition to calculating maximums and minimums, in SQL it's sometimes useful to calculate the <strong>ranking positions</strong> of elements based on the value of their metrics.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span>
  P1.PoolID,
  P1.Name,
  P1.MaxDepth,
  (
    <span class="hljs-keyword">SELECT</span> COUNT(*) + <span class="hljs-number">1</span>
    <span class="hljs-keyword">FROM</span> Pool <span class="hljs-keyword">AS</span> P2
    <span class="hljs-keyword">WHERE</span> P2.MaxDepth &gt; P1.MaxDepth
  ) <span class="hljs-keyword">AS</span> DepthRank
<span class="hljs-keyword">FROM</span> Pool <span class="hljs-keyword">AS</span> P1
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> DepthRank;
</code></pre>
<p>For example, in the query above, we get a list of all the pools in the database, where for each one, we calculate its position in the pool ranking ordered by the value of its <strong>MaxDepth</strong> attribute, that is, by its maximum depth.</p>
<p>Also, since there can be multiple pools with the same MaxDepth value, in that case, both pools will have the same position in the ranking. So the next position with a lower MaxDepth value won’t be the immediate next position – instead, you must add the number of pools from the previous position that had the same MaxDepth value to that ranking position.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>PoolID</strong></td><td><strong>Name</strong></td><td><strong>MaxDepth</strong></td><td><strong>DepthRank</strong></td></tr>
</thead>
<tbody>
<tr>
<td>1</td><td>Sample Pool Name 1</td><td>5</td><td>1</td></tr>
<tr>
<td>2</td><td>Sample Pool Name 2</td><td>5</td><td>1</td></tr>
<tr>
<td>3</td><td>Sample Pool Name 3</td><td>3</td><td>3</td></tr>
<tr>
<td>4</td><td>Sample Pool Name 4</td><td>2</td><td>4</td></tr>
<tr>
<td>5</td><td>Sample Pool Name 5</td><td>2</td><td>4</td></tr>
</tbody>
</table>
</div><p>To understand this, here we have a table where you can see that the first two pools have the same position (DepthRank) in the pool ranking because they have the same MaxDepth value. Then, the next pool with <strong>PoolID=3</strong> has position 3 in the ranking, as there are two pools before it in the ranking. Finally, the next two pools with <strong>PoolID=4</strong> and <strong>PoolID=5</strong> again have the same position in the ranking for the same reason as before.</p>
<p>As we can see, this way of defining and building the ranking is not what we might expect, where each pool has a unique position. Instead, we slightly modify the ranking definition to allow pools with the same MaxDepth value to share the same position in the ranking, so SQL implementation doesn't require more advanced functions.</p>
<p>Regarding the implementation, if we look at the attributes of the example table, specifically <strong>MaxDepth</strong> and its relationship with <strong>DepthRank</strong>, we can conclude that the position we should assign to each pool in the ranking matches the number of pools with a MaxDepth strictly greater than its own <strong>plus 1</strong>.</p>
<p>For example, for the pool with <strong>PoolID=2</strong>, we see that there is no pool with a MaxDepth greater than its own – at most, there are some with an equivalent MaxDepth, but never greater because this pool has the highest MaxDepth value (meaning the maximum). Meanwhile, the pool with <strong>PoolID=3</strong> has two pools with a MaxDepth greater than its own.</p>
<p>So if we <strong>add one</strong> to the number of pools with a metric value, which in this case we can find in the MaxDepth attribute, greater than the MaxDepth value of a certain pool, then the amount we obtain is the ranking position of that pool.</p>
<p>The simplest way to implement this calculation in SQL is through a correlated subquery in the SELECT, where, as you can see, we get all Pool tuples with a MaxDepth greater than the pool we are iterating over in the query. And finally, with <strong>COUNT(*)+1</strong>, we add 1 to the number of tuples returned by the subquery, thus generating the <strong>position</strong> in the ranking of the pool being iterated over in the query.</p>
<p>Continuing with the idea of getting the ranking position of the elements, we also have the option to select only those elements with a ranking position greater or less than a certain amount we need to set.</p>
<pre><code class="lang-pgsql"><span class="hljs-keyword">SELECT</span> PoolID, <span class="hljs-type">Name</span>, MaxDepth
<span class="hljs-keyword">FROM</span> Pool <span class="hljs-keyword">AS</span> P
<span class="hljs-keyword">WHERE</span> (
        <span class="hljs-keyword">SELECT</span> COUNT(*)
        <span class="hljs-keyword">FROM</span> Pool <span class="hljs-keyword">AS</span> P2
        <span class="hljs-keyword">WHERE</span> P2.MaxDepth &gt; P.MaxDepth
    ) &lt; <span class="hljs-number">5</span>
<span class="hljs-keyword">ORDER</span> <span class="hljs-keyword">BY</span> MaxDepth <span class="hljs-keyword">DESC</span>;
</code></pre>
<p>For example, above we have a query where we get the pools that are among the top 5 distinct positions in the ranking. In other words, we don’t get the first 5 rows with pools ordered in the ranking according to their MaxDepth value, but we get all those whose ranking position is among the top 5 distinct positions.</p>
<p>As you can see, the implementation is simple. We go through all the Pool tuples and for each one, we execute a subquery like the one we saw in the previous query: it gets the number of pools with a MaxDepth greater than the pool we are iterating over – that is, its position in the ranking. Then, we compare that number with 5 to ensure it’s strictly less.</p>
<p>Also, here we need to note that we have not added 1 to <strong>COUNT(*)</strong>, which means the ranking starts counting at <strong>position 0</strong>, not 1, so we can later check that the position is among the top 5 distinct ones with &lt; 5 and not &lt; 6. This doesn't have to be done this way necessarily, as we could have added 1 to <strong>COUNT(*)</strong> and declared the comparison using <strong>&lt;6</strong>, or <strong>&lt;=5</strong>.</p>
<p>In summary, in this query, we used a correlated subquery to get the ranking position (starting from position 0) of each pool, so we only keep those whose position is strictly less than 5. But we could have also pre-calculated the positions of each pool in a CTE and then applied this condition to an attribute instead of the value returned by a subquery.</p>
<p>This alternative will likely use more memory than is necessary, since the computing the execution of the subquery that calculates the ranking position will be present whether we use a CTE or not. So the most optimal approach would be to avoid wasting memory unless we really need an intermediate table with that information for other uses.</p>
<p>So now we’ve have seen a series of queries that follow certain patterns that are the most basic and fundamental in SQL. But there are many other queries we could perform on the schema of this example with a wide variety of purposes. These are <strong>essential</strong> to know how to formulate and code.</p>
<p>To learn more queries, you can visit the following resource: <strong>PostgreSQL.ipynb</strong>.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://github.com/cardstdani/sql-storage/blob/main/PostgreSQL.ipynb">https://github.com/cardstdani/sql-storage/blob/main/PostgreSQL.ipynb</a></div>
<p> </p>
<p>This is a Jupyter notebook that you can run from Google Collab. It contains Python code and Bash commands that allow you to install the <strong>PostgreSQL DBMS</strong> on a <strong>Linux virtual machine</strong> like those used by <a target="_blank" href="https://cloud.google.com/products/compute">Google Compute Engine</a> (the backend of Google Collab). You can also execute SQL code to create the database from the DDL and then run queries and obtain their results.</p>
<p>The notebook contains a series of query statements with solutions, along with everything needed to execute them. These queries aren’t ordered or classified like those we saw in the last chapter, as the goal is for you to try to solve them from the statements without looking at the solution. This way, you can later see how they were solved and gain practice in formulating queries, which is one of the most valuable skills for providing services to end users from the database.</p>
<p>You don’t necessarily have to do this in a Google Collab environment – you can also do it on a PostgreSQL installation on a <strong>local machine</strong> and execute the queries by copying and pasting the query code into the PostgreSQL terminal. But doing it in a remote environment like the one offered by Google Collab has certain advantages, such as not having to worry about installing anything manually, as everything is set up automatically by simply running the code cells or being able to see the text of the statements in the notebook rendered with markdown.</p>
<p>Still, there are some disadvantages, such as the database being stored on a Google virtual machine, which means you don't have full control over the machine and environment in which the DBMS runs. Its execution can also be interrupted depending on how you use the virtual machine and the plan you have with Google Collab.</p>
<p>So even though it may not be an environment where you can deploy a fully functional production database, it’s sufficiently similar to a real environment where you might have a database deployed for a project, making it worthwhile to work in Google Collab.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In this book, we’ve covered all the key concepts you need to know to design a database, based on certain requirements, for a software project.</p>
<p>But again, these concepts and commands are only the most basic and fundamental ones. So to learn more about SQL database design, check out other resources as well like reference books, articles, or the many resources available on the internet.</p>
<p>Your goal should be to gain a deeper understanding of what you’ve learned here. This will help you design robust DBs according to client requirements and code even more efficient queries.</p>
<p>Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ AI in Agriculture: How AI-Enhanced Farming Can Increase Crop Yields [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ Artificial intelligence is revolutionizing the agriculture industry, paving the way for a future of smarter, more efficient farming practices. Imagine a world where crops are grown with precision and care, maximizing yields like never before. With AI... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/ai-in-agriculture-book/</link>
                <guid isPermaLink="false">67867ea8a91f104f3f20e6a4</guid>
                
                    <category>
                        <![CDATA[ AI ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Artificial Intelligence ]]>
                    </category>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ AI Engineering ]]>
                    </category>
                
                    <category>
                        <![CDATA[ agriculture ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Vahe Aslanyan ]]>
                </dc:creator>
                <pubDate>Tue, 14 Jan 2025 15:11:36 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1736809244328/d4d5d757-b580-4c18-bc21-dad0bbd75f14.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Artificial intelligence is revolutionizing the agriculture industry, paving the way for a future of smarter, more efficient farming practices. Imagine a world where crops are grown with precision and care, maximizing yields like never before. With AI at the forefront, this vision is becoming a reality.</p>
<p>By harnessing the power of AI in agriculture, crop yields are projected to soar by an impressive 70% come 2030. But how exactly does AI-enhanced farming achieve such remarkable results? Let's dig deeper into the exciting realm of AI in agriculture and explore the boundless potential it holds.</p>
<h3 id="heading-what-youll-learn-here">What You’ll Learn Here</h3>
<p>In this book, we’ll delve into the fascinating ways in which AI technologies are transforming farming practices and boosting crop productivity to unprecedented levels.</p>
<p>Here's a glimpse of what you can expect to learn:</p>
<ul>
<li><p>The role of AI in optimizing crop cultivation techniques</p>
</li>
<li><p>How AI-powered tools enhance pest and disease management in agriculture</p>
</li>
<li><p>Real-life examples showcasing the impact of AI on farm efficiency</p>
</li>
<li><p>The future prospects and potential challenges of AI in agriculture</p>
</li>
</ul>
<p>Join me as we uncover the game-changing advancements in AI-driven farming and discover how these innovative solutions are reshaping the landscape of agriculture for the better.</p>
<h3 id="heading-table-of-contents">Table Of Contents</h3>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-to-expect-from-this-book">What to Expect from this Book</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-the-role-of-ai-in-transforming-agriculture">The Role of AI in Transforming Agriculture</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-1-precision-agriculture-techniques-and-benefits">Chapter 1: Precision Agriculture – Techniques and Benefits</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-2-how-to-enhance-crop-yields-and-productivity">Chapter 2: How to Enhance Crop Yields and Productivity</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-3-labor-optimization-solutions-through-ai-in-agriculture">Chapter 3: Labor Optimization Solutions Through AI in Agriculture</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-4-predictive-analytics-and-machine-learning-in-crop-yield-improvement">Chapter 4: Predictive Analytics and Machine Learning in Crop Yield Improvement</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-5-how-to-leverage-big-data-and-computer-vision-in-farming">Chapter 5: How to Leverage Big Data and Computer Vision in Farming</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-6-optimizing-soil-moisture-and-quality-with-ai-models">Chapter 6: Optimizing Soil Moisture and Quality with AI Models</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-7-sustainable-land-use-strategies-with-agricultural-technology">Chapter 7: Sustainable Land Use Strategies with Agricultural Technology</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-chapter-8-efficient-water-use-and-irrigation-systems-with-ai-guidance">Chapter 8: Efficient Water Use and Irrigation Systems with AI Guidance</a></p>
</li>
</ol>
<h2 id="heading-what-to-expect-from-this-book">What to Expect from this Book</h2>
<p>As the agricultural landscape evolves at a rapid pace, farmers, researchers, and industry leaders find themselves at a pivotal juncture.</p>
<p>Conventional methods that once guided decision-making—reliance on manual field assessments, guesswork in resource allocation, and labor-intensive processes—are quickly becoming outdated. In their place, data-driven insights, machine learning algorithms, and AI-enhanced technologies are redefining how we grow our food and manage our farms.</p>
<p>This book unravels the transformative potential of AI in agriculture, illustrating the tangible benefits and strategic advantages offered by this new era of farming.</p>
<p>By leveraging cutting-edge tools and analytics, the agricultural community can unlock untapped efficiencies, conserve vital resources, and achieve unprecedented boosts in productivity.</p>
<p>Above all, this integration of AI with agriculture isn’t about replacing human intelligence or experience—it’s about complementing it, magnifying the inherent wisdom farmers possess with the power of machine-driven insights.</p>
<p>Some of the major topics we’ll cover include:</p>
<ol>
<li><p><strong>Foundations of AI in Farming:</strong> Gain a solid understanding of the core principles of AI and how these technologies are applied to solve enduring farming challenges. Learn how sensors, drones, big data, and machine learning models come together to inform real-time decisions.</p>
</li>
<li><p><strong>Precision Agriculture at Scale:</strong> Discover how AI refines traditional practices by honing in on micro-level conditions—soil moisture, nutrient profiles, and localized weather patterns. Understand how precision agriculture tools empower you to apply the right resources at the right time, eliminating waste and maximizing yields.</p>
</li>
<li><p><strong>Adaptive Resource Management:</strong> Delve into predictive analytics that forecast weather events, identify pest infestations early, and recommend timely interventions. Explore how AI-driven recommendations save precious water, optimize fertilizer usage, and reduce overall costs, all while promoting long-term soil health and environmental stewardship.</p>
</li>
<li><p><strong>Robotics and Automation for Enhanced Efficiency:</strong> Uncover how AI, when paired with robotics and automation, tackles labor shortages, repetitive tasks, and harvest timing with surgical precision. From autonomous planting and weeding to advanced sorting systems, learn how farming operations can gain speed, accuracy, and reliability.</p>
</li>
<li><p><strong>Data-Driven Decision Making for Sustainability:</strong> Understand the data behind sustainable farming. Explore how integrating AI with ecological principles results in farming methods that are better for the planet and more profitable. See how smarter irrigation, targeted crop protection, and efficient land use not only improve the bottom line but also strengthen the resilience of farms against climate uncertainties.</p>
</li>
<li><p><strong>Global Food Security and Climate Adaptation:</strong> Examine the broader implications of AI adoption—from scaling food production to meet the needs of a rapidly growing global population, to adapting to extreme weather patterns. AI technology acts as a buffer, helping farmers pivot swiftly in response to environmental changes and market fluctuations.</p>
</li>
<li><p><strong>Overcoming Barriers and Realizing Potential:</strong> Identify the barriers to AI adoption, whether they be cost, technical literacy, or data sharing challenges. Learn strategies to overcome these hurdles, ensuring that farms of all sizes, from family-owned parcels to large commercial operations, can access and leverage AI insights.</p>
</li>
<li><p><strong>Financial Incentives and Market Opportunities:</strong> Explore how AI transforms farming from a precarious venture into a more predictable, profitable enterprise. Understand the financial incentives, loan programs, and investment avenues that encourage adopting advanced technologies. Discover how a data-driven approach not only lowers risks but opens doors to premium markets, certifications, and consumer trust.</p>
</li>
</ol>
<p>By the end of this book, you will have the confidence to integrate AI tools into your existing farm operations, knowing when and where each technology adds the most value.</p>
<p>You’ll also possess a refined set of strategies and best practices to make more informed, data-backed decisions that increase efficiency and reduce waste.</p>
<p>Your perspective on resource management, environmental stewardship, and long-term planning will also shift. You’ll learn how to achieve sustainable intensification, producing more with less and preserving the farm for future generations.</p>
<p>You’ll gain insights into how precision agriculture, robotics, data analytics, and predictive modeling directly contribute to better yields and higher returns on investment, building a financially resilient agricultural operation.</p>
<p>And finally, you will appreciate AI not as a complex, inaccessible science, but as a practical, essential toolkit for modern agriculture. This will position you at the forefront of an industry that’s poised for exponential growth and innovation, ready to increase crop yields by a remarkable 70% in the near future.</p>
<p>As you turn the pages ahead, prepare to envision a new era of farming—one where the synergy of human expertise and AI capabilities ensure a prosperous, sustainable, and secure food supply for all.</p>
<p>I’ve also <a target="_blank" href="https://open.spotify.com/episode/6hgUXtZnNjmgfl18fNWuLz?nd=1&amp;dlsi=51481ed967be42da">recorded a podcast</a> on this topic if you’d like to listen to that as well.</p>
<h2 id="heading-the-role-of-ai-in-transforming-agriculture">The Role of AI in Transforming Agriculture</h2>
<p>In recent years, the integration of artificial intelligence with agriculture has dramatically transformed traditional farming techniques, heralding a new era of productivity and sustainability.</p>
<p>This chapter examines the profound impact of AI on agriculture, offering an all-encompassing perspective on how AI can revolutionize farming practices, optimize crop yields, and promote environmental sustainability.</p>
<h3 id="heading-precision-agriculture-through-ai"><strong>Precision Agriculture through AI</strong></h3>
<p>Precision agriculture stands as a flagship application of AI within the agricultural domain. By allowing farmers to make highly informed decisions derived from granular data, AI elevates farming practices to unprecedented levels of efficiency and precision.</p>
<p>AI-driven systems analyze multifaceted data inputs, such as soil conditions, weather patterns, and crop performance metrics, creating a cohesive picture that empowers farmers to optimize every facet of crop management.</p>
<p>Rather than relying on broad-spectrum agricultural practices, precision agriculture tailors interventions to the unique needs of individual fields and even specific zones within those fields.</p>
<p>This hyper-local management not only maximizes crop yields but also curbs resource wastage, ultimately leading to a more sustainable and profitable farming operation. These data-driven decisions extend to optimal planting times, irrigation schedules, and fertilization plans, crafting an intricate roadmap to agricultural success.</p>
<p>In this example, we'll simulate how AI can help in precision agriculture by collecting soil data, weather data, and crop performance metrics. A model will be used to suggest optimal irrigation schedules and fertilization plans based on this data.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">from</span> sklearn.ensemble <span class="hljs-keyword">import</span> RandomForestRegressor

<span class="hljs-comment"># Sample data for soil moisture, temperature, and crop performance</span>
soil_moisture = np.array([<span class="hljs-number">30</span>, <span class="hljs-number">35</span>, <span class="hljs-number">32</span>, <span class="hljs-number">45</span>, <span class="hljs-number">40</span>])  <span class="hljs-comment"># percentage</span>
temperature = np.array([<span class="hljs-number">18</span>, <span class="hljs-number">21</span>, <span class="hljs-number">19</span>, <span class="hljs-number">23</span>, <span class="hljs-number">22</span>])    <span class="hljs-comment"># Celsius</span>
crop_yield = np.array([<span class="hljs-number">80</span>, <span class="hljs-number">85</span>, <span class="hljs-number">83</span>, <span class="hljs-number">90</span>, <span class="hljs-number">88</span>])     <span class="hljs-comment"># yield per hectare</span>

<span class="hljs-comment"># Labels for optimal irrigation and fertilization in percentage</span>
irrigation = np.array([<span class="hljs-number">20</span>, <span class="hljs-number">25</span>, <span class="hljs-number">22</span>, <span class="hljs-number">30</span>, <span class="hljs-number">28</span>])   <span class="hljs-comment"># water in percentage</span>
fertilizer = np.array([<span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">5</span>, <span class="hljs-number">7</span>, <span class="hljs-number">6</span>])        <span class="hljs-comment"># fertilizer in kg/ha</span>

<span class="hljs-comment"># Train a model for irrigation schedule</span>
irrigation_model = RandomForestRegressor()
irrigation_model.fit(np.column_stack((soil_moisture, temperature, crop_yield)), irrigation)

<span class="hljs-comment"># Train a model for fertilizer schedule</span>
fertilizer_model = RandomForestRegressor()
fertilizer_model.fit(np.column_stack((soil_moisture, temperature, crop_yield)), fertilizer)

<span class="hljs-comment"># Simulating new data for a prediction</span>
new_soil_moisture = <span class="hljs-number">38</span>
new_temperature = <span class="hljs-number">20</span>
new_crop_yield = <span class="hljs-number">85</span>

predicted_irrigation = irrigation_model.predict([[new_soil_moisture, new_temperature, new_crop_yield]])
predicted_fertilizer = fertilizer_model.predict([[new_soil_moisture, new_temperature, new_crop_yield]])

print(<span class="hljs-string">f"Predicted irrigation schedule: <span class="hljs-subst">{predicted_irrigation[<span class="hljs-number">0</span>]:<span class="hljs-number">.2</span>f}</span>% water"</span>)
print(<span class="hljs-string">f"Predicted fertilizer plan: <span class="hljs-subst">{predicted_fertilizer[<span class="hljs-number">0</span>]:<span class="hljs-number">.2</span>f}</span> kg/ha"</span>)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725970849931/b3f762f2-03d5-4ec2-ac45-4369737be093.png" alt="A screenshot of a Python code script. The script uses the RandomForestRegressor from the sklearn.ensemble module to predict irrigation schedules and fertilizer plans based on soil moisture, temperature, and crop yield data. The code creates arrays for each variable and trains models for irrigation and fertilizer schedules. It then simulates new data for prediction and prints the predicted irrigation schedule and fertilizer plan." class="image--center mx-auto" width="2036" height="1488" loading="lazy"></a></p>
<h3 id="heading-machine-learning-pioneering-predictive-crop-management"><strong>Machine Learning: Pioneering Predictive Crop Management</strong></h3>
<p>In the realm of modern agriculture, machine learning algorithms have emerged as indispensable assets. These algorithms digest vast, complex datasets encompassing soil moisture levels, plant health monitoring indicators, and meteorological forecasts, to develop predictive analytics models.</p>
<p>These models empower farmers to anticipate crop outcomes, facilitating proactive interventions designed to mitigate potential risks and bolster productivity.</p>
<p>For instance, by forecasting potential pest infestations or disease outbreaks, farmers can implement timely preventive measures, safeguarding crop health and ensuring optimal yield. This predictive capability extends beyond immediate crop management, aiding in long-term planning for resource allocation and operational logistics. The integration of machine learning not only enhances current farming practices but also fortifies the agricultural sector against future challenges.</p>
<p>In this code snippet, a machine learning model predicts the likelihood of a pest infestation based on factors like soil moisture and weather conditions.</p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> sklearn.linear_model <span class="hljs-keyword">import</span> LogisticRegression

<span class="hljs-comment"># Sample data (soil moisture, temperature, pest infestation - 0 means no infestation, 1 means infestation)</span>
data = np.array([[<span class="hljs-number">30</span>, <span class="hljs-number">22</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">35</span>, <span class="hljs-number">25</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">40</span>, <span class="hljs-number">28</span>, <span class="hljs-number">1</span>], [<span class="hljs-number">25</span>, <span class="hljs-number">20</span>, <span class="hljs-number">0</span>], [<span class="hljs-number">45</span>, <span class="hljs-number">30</span>, <span class="hljs-number">1</span>]])
X = data[:, :<span class="hljs-number">2</span>]  <span class="hljs-comment"># Soil moisture, temperature</span>
y = data[:, <span class="hljs-number">2</span>]   <span class="hljs-comment"># Pest infestation</span>

<span class="hljs-comment"># Train a Logistic Regression model</span>
pest_model = LogisticRegression()
pest_model.fit(X, y)

<span class="hljs-comment"># Predicting on new data</span>
new_soil_moisture = <span class="hljs-number">33</span>
new_temperature = <span class="hljs-number">27</span>

predicted_pest_risk = pest_model.predict([[new_soil_moisture, new_temperature]])
predicted_prob = pest_model.predict_proba([[new_soil_moisture, new_temperature]])[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>]

<span class="hljs-keyword">if</span> predicted_pest_risk[<span class="hljs-number">0</span>] == <span class="hljs-number">1</span>:
    print(<span class="hljs-string">f"High risk of pest infestation! Probability: <span class="hljs-subst">{predicted_prob:<span class="hljs-number">.2</span>f}</span>"</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">f"Low risk of pest infestation. Probability: <span class="hljs-subst">{predicted_prob:<span class="hljs-number">.2</span>f}</span>"</span>)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725970933643/393990d8-48bd-4ca9-ace8-3095b309284b.png" alt="393990d8-48bd-4ca9-ace8-3095b309284b" class="image--center mx-auto" width="2048" height="1228" loading="lazy"></a></p>
<h3 id="heading-farm-operations-transformed-by-computer-vision"><strong>Farm Operations Transformed by Computer Vision</strong></h3>
<p>Computer vision technology propels agriculture into a new frontier, where machines possess the ability to "see" and interpret visual data with astounding accuracy. Employing sophisticated cameras and sensors, computer vision systems meticulously monitor crop health, detect and identify pest infestations, and evaluate soil quality in real-time.</p>
<p>The precision of computer vision enables the early detection of subtle changes in crop health that might elude the human eye. By identifying stressors such as nutrient deficiencies or water stress early, farmers can initiate targeted interventions, promoting healthier crops and improved yields.</p>
<p>This technology not only ensures timely management but also reduces the reliance on chemical treatments, fostering a more sustainable approach to pest and disease control.</p>
<p>Here, we simulate a simple computer vision task to detect unhealthy crops using image data, where red areas in the crop image might indicate stress or disease.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> cv2
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Simulate a crop image with random red patches (signifying stress)</span>
image = np.zeros((<span class="hljs-number">100</span>, <span class="hljs-number">100</span>, <span class="hljs-number">3</span>), dtype=<span class="hljs-string">"uint8"</span>)
cv2.rectangle(image, (<span class="hljs-number">30</span>, <span class="hljs-number">30</span>), (<span class="hljs-number">70</span>, <span class="hljs-number">70</span>), (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>), <span class="hljs-number">-1</span>)  <span class="hljs-comment"># Simulating stress area</span>

<span class="hljs-comment"># Convert to HSV to detect red areas</span>
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower_red = np.array([<span class="hljs-number">0</span>, <span class="hljs-number">120</span>, <span class="hljs-number">70</span>])
upper_red = np.array([<span class="hljs-number">10</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>])
mask = cv2.inRange(hsv_image, lower_red, upper_red)

<span class="hljs-comment"># Calculate percentage of red (stressed) area</span>
red_area_percentage = np.sum(mask &gt; <span class="hljs-number">0</span>) / (image.shape[<span class="hljs-number">0</span>] * image.shape[<span class="hljs-number">1</span>]) * <span class="hljs-number">100</span>

<span class="hljs-keyword">if</span> red_area_percentage &gt; <span class="hljs-number">10</span>:
    print(<span class="hljs-string">f"Alert! <span class="hljs-subst">{red_area_percentage:<span class="hljs-number">.2</span>f}</span>% of the crop area shows signs of stress."</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">f"Healthy crops. Only <span class="hljs-subst">{red_area_percentage:<span class="hljs-number">.2</span>f}</span>% of the area shows stress."</span>)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725970966792/df5ce229-ed33-4601-a2fd-a4364a1b171f.png" alt="The image shows a Python script for detecting and calculating the percentage of red areas in an image, which simulates stressed crop patches. The script uses OpenCV and NumPy libraries to create an image with a red rectangle, convert the image to HSV color space, detect the red areas, and then print a message based on the percentage of detected red areas indicating stress. - lunartech.ai" class="image--center mx-auto" width="1766" height="1116" loading="lazy"></a></p>
<h3 id="heading-ai-driven-sustainability-in-agriculture"><strong>AI-Driven Sustainability in Agriculture</strong></h3>
<p>One of the most compelling promises of AI in agriculture lies in its potential to drive sustainability. Through optimized land use and resource management, AI models contribute to reducing the environmental footprint of farming activities. AI algorithms can recommend precise dosages of water, fertilizers, and pesticides, minimizing overuse and runoff that can harm surrounding ecosystems.</p>
<p>AI's ability to analyze and predict climate patterns also supports the development of resilient agricultural practices. By helping farmers adapt to changing weather conditions and extreme events, AI fosters a more stable and sustainable food production system. This aspect is particularly crucial in the face of global climate change and the increasing demand for food from a growing population.</p>
<p>In this example, AI recommends optimal resource usage (water and fertilizer) based on predicted environmental data to minimize resource waste.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Environmental and crop data</span>
rainfall_forecast = <span class="hljs-number">50</span>  <span class="hljs-comment"># mm</span>
soil_type = <span class="hljs-string">'clay'</span>  <span class="hljs-comment"># clay, sand, silt</span>
crop_stage = <span class="hljs-string">'vegetative'</span>  <span class="hljs-comment"># stages: seedling, vegetative, reproductive</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">recommend_water</span>(<span class="hljs-params">rainfall, soil, stage</span>):</span>
    base_water = <span class="hljs-number">20</span>  <span class="hljs-comment"># base liters per hectare</span>
    <span class="hljs-keyword">if</span> soil == <span class="hljs-string">'sand'</span>:
        base_water += <span class="hljs-number">5</span>
    <span class="hljs-keyword">if</span> stage == <span class="hljs-string">'reproductive'</span>:
        base_water += <span class="hljs-number">10</span>

    <span class="hljs-keyword">if</span> rainfall &gt; <span class="hljs-number">30</span>:
        base_water -= <span class="hljs-number">5</span>  <span class="hljs-comment"># reduce water if heavy rain predicted</span>

    <span class="hljs-keyword">return</span> max(base_water, <span class="hljs-number">5</span>)

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">recommend_fertilizer</span>(<span class="hljs-params">stage</span>):</span>
    <span class="hljs-keyword">if</span> stage == <span class="hljs-string">'seedling'</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-number">3</span>  <span class="hljs-comment"># kg/ha</span>
    <span class="hljs-keyword">elif</span> stage == <span class="hljs-string">'vegetative'</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-number">6</span>
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-number">10</span>

<span class="hljs-comment"># Predictions for optimal resources</span>
optimal_water = recommend_water(rainfall_forecast, soil_type, crop_stage)
optimal_fertilizer = recommend_fertilizer(crop_stage)

print(<span class="hljs-string">f"Optimal water usage: <span class="hljs-subst">{optimal_water:<span class="hljs-number">.2</span>f}</span> liters per hectare"</span>)
print(<span class="hljs-string">f"Optimal fertilizer dosage: <span class="hljs-subst">{optimal_fertilizer:<span class="hljs-number">.2</span>f}</span> kg/ha"</span>)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725971051009/22e678ab-a31f-4228-837c-b56065a1214b.png" alt="A screenshot of a Python code script is displayed. The script defines environmental and crop data parameters such as rainfall forecast, soil type, and crop stage. It includes two functions:  which calculates the recommended water based on rainfall, soil, and stage, and  which calculates the recommended fertilizer based on the crop stage. The script computes the optimal water usage and fertilizer dosage, and prints these values." class="image--center mx-auto" width="1530" height="1526" loading="lazy"></a></p>
<h3 id="heading-addressing-future-agricultural-challenges-with-ai"><strong>Addressing Future Agricultural Challenges with AI</strong></h3>
<p>The agricultural sector stands at a crossroads, confronted by an array of challenges including labor shortages, extreme weather events, and the imperative for enhanced decision-making tools.</p>
<p>AI-powered solutions present a beacon of hope, offering tools and methodologies to navigate these obstacles effectively. By automating labor-intensive tasks such as planting and harvesting, AI eases the burden on the agricultural workforce.</p>
<p>Beyond this, AI's analytical capabilities provide farmers with the insights needed to adapt to evolving environmental and market conditions. Enhanced resilience is key, as the ability to swiftly respond to unforeseen challenges ensures the continuity of agricultural production and security of food supplies.</p>
<p>The transformation is not limited to technological or productivity aspects alone. AI also cultivates a mindset of continuous improvement and learning within the agricultural community. By embracing data-centric approaches and fostering an environment of innovation, AI nurtures a new generation of farmers equipped to tackle the intricacies of modern agriculture.</p>
<p>This example demonstrates how AI can assist in automating tasks like identifying ripened crops for automated harvesting using basic image processing.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> cv2

<span class="hljs-comment"># Simulate crop image with different shades (representing ripened and unripened crops)</span>
image = np.zeros((<span class="hljs-number">100</span>, <span class="hljs-number">100</span>, <span class="hljs-number">3</span>), dtype=<span class="hljs-string">"uint8"</span>)
cv2.circle(image, (<span class="hljs-number">30</span>, <span class="hljs-number">30</span>), <span class="hljs-number">20</span>, (<span class="hljs-number">0</span>, <span class="hljs-number">255</span>, <span class="hljs-number">0</span>), <span class="hljs-number">-1</span>)  <span class="hljs-comment"># Green (unripe crop)</span>
cv2.circle(image, (<span class="hljs-number">70</span>, <span class="hljs-number">70</span>), <span class="hljs-number">20</span>, (<span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">255</span>), <span class="hljs-number">-1</span>)  <span class="hljs-comment"># Red (ripe crop)</span>

<span class="hljs-comment"># Convert image to HSV to detect red (ripened crops)</span>
hsv_image = cv2.cvtColor(image, cv2.COLOR_BGR2HSV)
lower_red = np.array([<span class="hljs-number">0</span>, <span class="hljs-number">120</span>, <span class="hljs-number">70</span>])
upper_red = np.array([<span class="hljs-number">10</span>, <span class="hljs-number">255</span>, <span class="hljs-number">255</span>])
mask = cv2.inRange(hsv_image, lower_red, upper_red)

<span class="hljs-comment"># Identify ripe crops for harvesting</span>
ripe_area_percentage = np.sum(mask &gt; <span class="hljs-number">0</span>) / (image.shape[<span class="hljs-number">0</span>] * image.shape[<span class="hljs-number">1</span>]) * <span class="hljs-number">100</span>

<span class="hljs-keyword">if</span> ripe_area_percentage &gt; <span class="hljs-number">10</span>:
    print(<span class="hljs-string">f"Ripe crops detected! <span class="hljs-subst">{ripe_area_percentage:<span class="hljs-number">.2</span>f}</span>% of the area is ready for harvest."</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">f"Insufficient ripeness. <span class="hljs-subst">{ripe_area_percentage:<span class="hljs-number">.2</span>f}</span>% of the area is ready for harvest."</span>)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725971143619/2bb7ac42-0738-4112-bf44-906f2098d1fb.png" alt="A screenshot of a Python code snippet using OpenCV and NumPy libraries to detect and identify ripe crops. The code simulates an image with different shades representing ripened and unripened crops, converts the image to HSV color space, creates a mask to detect red (ripened) areas, and calculates the percentage of the image that is ripe. The result is printed based on the percentage of ripe crops detected." class="image--center mx-auto" width="1952" height="1116" loading="lazy"></a></p>
<p>As you can now start to see, the integration of AI in agriculture is shaping the future of farming by moving beyond traditional methods and unlocking a plethora of possibilities for enhanced crop management, sustainability, and resilience.</p>
<p>By leveraging precision agriculture, machine learning, computer vision, and sustainability-focused AI models, the agricultural sector is poised to meet future challenges head-on, ensuring food security and environmental stewardship for generations to come.</p>
<p>The cumulative impact of these advanced technologies holds the potential to increase crop yields significantly, setting a path toward a more productive and sustainable agricultural industry by 2030 and beyond.</p>
<h2 id="heading-chapter-1-precision-agriculture-techniques-and-benefits">Chapter 1: Precision Agriculture – Techniques and Benefits</h2>
<p>AI and and other cutting-edge technologies are revolutionizing the agriculture industry, providing innovative solutions to enhance crop yields and address the myriad challenges faced by farmers globally. With the advent of AI models, predictive analytics, and machine learning algorithms, the agricultural sector can now leverage real-time data for more informed decision-making.</p>
<p>This chapter explores the profound impact of these technologies, offering a comprehensive analysis of their applications and benefits.</p>
<p>For each subsection below, you’ll find code snippets that demonstrate how these practices can work. These examples incorporate Large Language Models (LLMs) to enhance various agricultural applications.</p>
<p>The code primarily uses Python and integrates OpenAI's GPT models via their API. Ensure you have the <code>openai</code> library installed and have set up your API key before running these examples.</p>
<pre><code class="lang-bash">pip install openai
</code></pre>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai
<span class="hljs-keyword">import</span> os

<span class="hljs-comment"># Set your OpenAI API key</span>
openai.api_key = os.getenv(<span class="hljs-string">"OPENAI_API_KEY"</span>)
</code></pre>
<p>Now that you’re all set, let’s examine some of the different ways that AI can have an impact on agricultural practices.</p>
<h3 id="heading-predictive-analytics-in-agriculture"><strong>Predictive Analytics in Agriculture</strong></h3>
<p>Predictive analytics represents a significant advancement in the agricultural domain. By meticulously analyzing weather patterns, soil conditions, and historical crop data, farmers can proactively adapt their strategies to mitigate risks and optimize yields.</p>
<p>For instance, predictive models can forecast the likelihood of drought or pest infestations, allowing farmers to deploy preventive measures well in advance. This data-driven approach ensures farming practices are not only more responsive but also tailored to specific soil types and crop needs.</p>
<p>Consider a farmer in the Midwest United States dealing with unpredictable weather patterns. By using predictive analytics, this farmer can receive timely alerts about incoming weather changes, enabling them to adjust crop schedules, irrigation, and even planting strategies accordingly. The integration of satellite imagery and IoT sensors provides a holistic view of the farm’s health, ensuring that every decision is backed by robust data.</p>
<h4 id="heading-example-of-predictive-analysis-in-agriculture"><strong>Example of predictive analysis in agriculture:</strong></h4>
<p><strong>Objective:</strong> Utilize an LLM to generate actionable insights from predictive analytics models, such as forecasting drought risks or pest infestations.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">from</span> sklearn.ensemble <span class="hljs-keyword">import</span> RandomForestClassifier

<span class="hljs-comment"># Sample data: [soil_moisture, temperature, humidity]</span>
X = np.array([
    [<span class="hljs-number">30</span>, <span class="hljs-number">25</span>, <span class="hljs-number">40</span>],
    [<span class="hljs-number">35</span>, <span class="hljs-number">30</span>, <span class="hljs-number">50</span>],
    [<span class="hljs-number">20</span>, <span class="hljs-number">15</span>, <span class="hljs-number">30</span>],
    [<span class="hljs-number">25</span>, <span class="hljs-number">20</span>, <span class="hljs-number">35</span>],
    [<span class="hljs-number">40</span>, <span class="hljs-number">35</span>, <span class="hljs-number">60</span>]
])

<span class="hljs-comment"># Labels: 0 - No pest infestation, 1 - Pest infestation</span>
y = np.array([<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>])

<span class="hljs-comment"># Train a predictive model</span>
model = RandomForestClassifier()
model.fit(X, y)

<span class="hljs-comment"># New data point</span>
new_data = np.array([[<span class="hljs-number">28</span>, <span class="hljs-number">22</span>, <span class="hljs-number">45</span>]])

<span class="hljs-comment"># Predict pest infestation</span>
prediction = model.predict(new_data)[<span class="hljs-number">0</span>]
probability = model.predict_proba(new_data)[<span class="hljs-number">0</span>][<span class="hljs-number">1</span>]

<span class="hljs-comment"># Generate a natural language report using LLM</span>
<span class="hljs-keyword">if</span> prediction == <span class="hljs-number">1</span>:
    risk = <span class="hljs-string">f"High risk of pest infestation with a probability of <span class="hljs-subst">{probability*<span class="hljs-number">100</span>:<span class="hljs-number">.2</span>f}</span>%."</span>
<span class="hljs-keyword">else</span>:
    risk = <span class="hljs-string">f"Low risk of pest infestation with a probability of <span class="hljs-subst">{(<span class="hljs-number">1</span> - probability)*<span class="hljs-number">100</span>:<span class="hljs-number">.2</span>f}</span>%."</span>

<span class="hljs-comment"># Use LLM to create a comprehensive report</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an agricultural data analyst."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Generate a report based on the following risk assessment: <span class="hljs-subst">{risk}</span>"</span>}
    ]
)

report = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(report)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973300463/90fd2b54-6c1c-43f9-8f2e-53ba7a362444.png" alt="A screenshot showing a Python script for predicting pest infestation using machine learning and a language model. The script imports necessary libraries, defines sample data, and uses a RandomForestClassifier to train a predictive model. It then generates a natural language report on pest infestation risk assessment using OpenAI's GPT-4. - https://lunartech.ai" class="image--center mx-auto" width="2048" height="2046" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">Based on the latest data analysis, there <span class="hljs-keyword">is</span> a high risk of pest infestation <span class="hljs-keyword">with</span> a probability of <span class="hljs-number">70.00</span>%. It <span class="hljs-keyword">is</span> recommended to implement preventive measures such <span class="hljs-keyword">as</span> targeted pesticide application <span class="hljs-keyword">and</span> increased monitoring <span class="hljs-keyword">in</span> the affected areas to mitigate potential damage <span class="hljs-keyword">and</span> ensure optimal crop health.
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973339330/02d51d54-3b9e-469b-899d-ba6e1a8f43cc.png" alt="Text on a dark background states: &quot;Based on the latest data analysis, there is a high risk of pest infestation with a probability of 70.00%. It is recommended to implement preventive measures such as targeted pesticide application and increased monitoring in the affected areas to mitigate potential damage and ensure optimal crop health.&quot; - lunartech.ai" class="image--center mx-auto" width="2048" height="484" loading="lazy"></a></p>
<h3 id="heading-precision-agriculture-techniques"><strong>Precision Agriculture Techniques</strong></h3>
<p>AI-powered machine learning algorithms are central to the practice of precision agriculture, a method that optimizes the management of farming practices. Machine learning aids in monitoring various critical parameters such as soil moisture, nutrient levels, and crop health with unparalleled precision.</p>
<p>By utilizing computer vision technology, farmers can remotely assess the health of their crops through high-resolution images. This technology identifies areas requiring immediate attention, thereby significantly reducing waste and enhancing productivity.</p>
<p>For example, a farmer in the rice-producing regions of Asia can use drones equipped with multi-spectral cameras to monitor crop conditions. The data captured is processed through AI algorithms that provide actionable insights on which areas need additional water or which sections are experiencing nutrient deficiencies. This precise targeting ensures resources are utilized efficiently, promoting sustainable farming practices while increasing yields.</p>
<h4 id="heading-example-of-using-precision-agriculture-techniques"><strong>Example of using precision agriculture techniques</strong></h4>
<p><strong>Objective:</strong> Use an LLM to interpret data from precision agriculture sensors and provide tailored recommendations.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample sensor data</span>
sensor_data = {
    <span class="hljs-string">"soil_moisture"</span>: <span class="hljs-number">35</span>,  <span class="hljs-comment"># in percentage</span>
    <span class="hljs-string">"temperature"</span>: <span class="hljs-number">22</span>,    <span class="hljs-comment"># in Celsius</span>
    <span class="hljs-string">"nutrient_levels"</span>: {
        <span class="hljs-string">"nitrogen"</span>: <span class="hljs-number">50</span>,    <span class="hljs-comment"># ppm</span>
        <span class="hljs-string">"phosphorus"</span>: <span class="hljs-number">30</span>,  <span class="hljs-comment"># ppm</span>
        <span class="hljs-string">"potassium"</span>: <span class="hljs-number">40</span>    <span class="hljs-comment"># ppm</span>
    },
    <span class="hljs-string">"crop_stage"</span>: <span class="hljs-string">"vegetative"</span>
}

<span class="hljs-comment"># Convert sensor data to a descriptive text</span>
data_description = (
    <span class="hljs-string">f"Soil moisture is at <span class="hljs-subst">{sensor_data[<span class="hljs-string">'soil_moisture'</span>]}</span>%, "</span>
    <span class="hljs-string">f"temperature is <span class="hljs-subst">{sensor_data[<span class="hljs-string">'temperature'</span>]}</span>°C, "</span>
    <span class="hljs-string">f"nitrogen levels are <span class="hljs-subst">{sensor_data[<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'nitrogen'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"phosphorus levels are <span class="hljs-subst">{sensor_data[<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'phosphorus'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"potassium levels are <span class="hljs-subst">{sensor_data[<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'potassium'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"and the crop is in the <span class="hljs-subst">{sensor_data[<span class="hljs-string">'crop_stage'</span>]}</span> stage."</span>
)

<span class="hljs-comment"># Use LLM to generate recommendations</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an expert in precision agriculture."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following sensor data, provide recommendations for irrigation and fertilization: <span class="hljs-subst">{data_description}</span>"</span>}
    ]
)

recommendations = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(recommendations)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973386647/b96164bf-beb4-4061-ad07-ad96ea38a12a.png" alt="A code snippet written in Python that uses the OpenAI API to generate agricultural recommendations. The script defines sample sensor data (soil moisture, temperature, nitrogen, phosphorus, potassium levels, and crop stage), converts the sensor data into a descriptive format, and sends this information to the OpenAI Model (GPT-4) to request recommendations for irrigation and fertilization. The response is printed at the end." class="image--center mx-auto" width="2048" height="1712" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">Based on the current sensor data, here are the recommendations:

**Irrigation:**
- Soil moisture <span class="hljs-keyword">is</span> at <span class="hljs-number">35</span>%, which <span class="hljs-keyword">is</span> within the optimal range <span class="hljs-keyword">for</span> the vegetative stage. Continue <span class="hljs-keyword">with</span> the current irrigation schedule but monitor closely <span class="hljs-keyword">for</span> any fluctuations due to temperature changes.

**Fertilization:**
- **Nitrogen (<span class="hljs-number">50</span> ppm):** Adequate <span class="hljs-keyword">for</span> the vegetative stage. No additional nitrogen fertilizer <span class="hljs-keyword">is</span> needed at this time.
- **Phosphorus (<span class="hljs-number">30</span> ppm):** Levels are slightly low. Consider applying a phosphorus-based fertilizer to support root development.
- **Potassium (<span class="hljs-number">40</span> ppm):** Adequate. Maintain current potassium levels to ensure balanced nutrient availability.

Overall, maintain regular monitoring <span class="hljs-keyword">and</span> adjust <span class="hljs-keyword">as</span> necessary based on plant responses <span class="hljs-keyword">and</span> environmental conditions.
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973431656/6c01108c-ed30-41df-88d4-8036d2a0bd99.png" alt="A text box on a dark background provides agricultural recommendations based on current sensor data. For irrigation, the soil moisture is at 35%, which is optimal. For fertilization, nitrogen (50 ppm) is adequate, phosphorus (30 ppm) is slightly low, and potassium (40 ppm) is adequate. The overall advice is to maintain regular monitoring and make adjustments based on plant responses and environmental conditions." class="image--center mx-auto" width="2048" height="968" loading="lazy"></a></p>
<h3 id="heading-enhancing-soil-quality-and-productivity"><strong>Enhancing Soil Quality and Productivity</strong></h3>
<p>Soil quality is a critical factor in determining crop productivity. AI-enhanced farm management software equips farmers with the tools to monitor and improve soil health continuously.</p>
<p>By understanding the specific characteristics of their soil, such as pH levels, nutrient content, and organic matter, farmers can implement targeted interventions. This precision management approach maximizes the use of resources while promoting soil sustainability.</p>
<p>Consider a farmer in sub-Saharan Africa struggling with nutrient-poor soils. AI can analyze soil samples and recommend precise formulations of fertilizers tailored to the specific needs of the soil. Over time, the software can track the impact of these interventions, providing feedback and suggesting further improvements. This continuous optimization cycle not only boosts crop yields but also enhances soil health, ensuring long-term sustainability.</p>
<h4 id="heading-example-of-enhancing-soil-quality-and-productivity"><strong>Example of enhancing soil quality and productivity</strong></h4>
<p><strong>Objective:</strong> Leverage an LLM to analyze soil data and recommend precise fertilizer formulations tailored to specific soil needs.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample soil data</span>
soil_data = {
    <span class="hljs-string">"pH"</span>: <span class="hljs-number">5.8</span>,
    <span class="hljs-string">"organic_matter"</span>: <span class="hljs-number">3.2</span>,  <span class="hljs-comment"># percentage</span>
    <span class="hljs-string">"nutrient_content"</span>: {
        <span class="hljs-string">"nitrogen"</span>: <span class="hljs-number">40</span>,       <span class="hljs-comment"># ppm</span>
        <span class="hljs-string">"phosphorus"</span>: <span class="hljs-number">25</span>,     <span class="hljs-comment"># ppm</span>
        <span class="hljs-string">"potassium"</span>: <span class="hljs-number">35</span>       <span class="hljs-comment"># ppm</span>
    },
    <span class="hljs-string">"crop_type"</span>: <span class="hljs-string">"corn"</span>
}

<span class="hljs-comment"># Create a descriptive text from soil data</span>
soil_description = (
    <span class="hljs-string">f"The soil pH is <span class="hljs-subst">{soil_data[<span class="hljs-string">'pH'</span>]}</span>, organic matter is <span class="hljs-subst">{soil_data[<span class="hljs-string">'organic_matter'</span>]}</span>%, "</span>
    <span class="hljs-string">f"nitrogen level is <span class="hljs-subst">{soil_data[<span class="hljs-string">'nutrient_content'</span>][<span class="hljs-string">'nitrogen'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"phosphorus level is <span class="hljs-subst">{soil_data[<span class="hljs-string">'nutrient_content'</span>][<span class="hljs-string">'phosphorus'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"potassium level is <span class="hljs-subst">{soil_data[<span class="hljs-string">'nutrient_content'</span>][<span class="hljs-string">'potassium'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"and the crop type is <span class="hljs-subst">{soil_data[<span class="hljs-string">'crop_type'</span>]}</span>."</span>
)

<span class="hljs-comment"># Use LLM to recommend fertilizer formulations</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are a soil fertility expert."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following soil data, recommend precise fertilizer formulations for optimal corn growth: <span class="hljs-subst">{soil_description}</span>"</span>}
    ]
)

fertilizer_recommendations = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(fertilizer_recommendations)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973480851/37846587-3606-4bd1-9de9-e88a21d76bc8.png" alt="A code snippet is displayed showing the use of the OpenAI GPT-4 model to generate soil fertility recommendations. The script includes sample soil data, constructs a descriptive text from this data, and queries the GPT-4 model for fertilizer formulations based on the soil description." class="image--center mx-auto" width="2048" height="1674" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">Based on the provided soil data, here are the fertilizer recommendations <span class="hljs-keyword">for</span> optimal corn growth:

**Soil pH: <span class="hljs-number">5.8</span>**
- Slightly acidic <span class="hljs-keyword">for</span> corn, which prefers a pH between <span class="hljs-number">6.0</span> <span class="hljs-keyword">and</span> <span class="hljs-number">6.8</span>. To <span class="hljs-keyword">raise</span> the pH, consider applying agricultural lime at a rate of <span class="hljs-number">1</span><span class="hljs-number">-2</span> tons per acre. Conduct a soil test after a few months to determine <span class="hljs-keyword">if</span> further adjustments are necessary.

**Organic Matter: <span class="hljs-number">3.2</span>%**
- Adequate organic matter content. Maintain <span class="hljs-keyword">or</span> slightly increase it by incorporating compost <span class="hljs-keyword">or</span> well-decomposed manure to enhance soil structure <span class="hljs-keyword">and</span> nutrient retention.

**Nutrient Content:**
- **Nitrogen (<span class="hljs-number">40</span> ppm):** Adequate <span class="hljs-keyword">for</span> early growth stages. Apply a balanced nitrogen fertilizer, such <span class="hljs-keyword">as</span> urea (<span class="hljs-number">46</span><span class="hljs-number">-0</span><span class="hljs-number">-0</span>), at a rate of <span class="hljs-number">50</span><span class="hljs-number">-60</span> lbs per acre at planting, followed by a side-dress application of <span class="hljs-number">30</span><span class="hljs-number">-40</span> lbs per acre when plants reach the V6 stage.

- **Phosphorus (<span class="hljs-number">25</span> ppm):** Slightly low <span class="hljs-keyword">for</span> corn, which requires higher phosphorus <span class="hljs-keyword">for</span> root development. Apply a phosphorus fertilizer like triple superphosphate (<span class="hljs-number">0</span><span class="hljs-number">-46</span><span class="hljs-number">-0</span>) at a rate of <span class="hljs-number">20</span><span class="hljs-number">-30</span> lbs per acre during planting.

- **Potassium (<span class="hljs-number">35</span> ppm):** Adequate <span class="hljs-keyword">for</span> corn growth. Maintain current levels by applying potassium sulfate (<span class="hljs-number">0</span><span class="hljs-number">-0</span><span class="hljs-number">-50</span>) <span class="hljs-keyword">if</span> necessary, but based on current data, additional potassium may <span class="hljs-keyword">not</span> be required.

**Crop Type: Corn**
- Corn has high nutrient demands, especially nitrogen <span class="hljs-keyword">and</span> phosphorus. Regularly monitor plant growth <span class="hljs-keyword">and</span> soil nutrient levels throughout the growing season to adjust fertilizer applications <span class="hljs-keyword">as</span> needed.

**Additional Recommendations:**
- Implement a crop rotation plan to prevent nutrient depletion <span class="hljs-keyword">and</span> reduce pest <span class="hljs-keyword">and</span> disease pressure.
- Utilize cover crops during off-season periods to enhance soil fertility <span class="hljs-keyword">and</span> organic matter.
- Ensure proper irrigation management to facilitate nutrient uptake <span class="hljs-keyword">and</span> prevent leaching.

These tailored fertilizer formulations will support robust corn growth, improve <span class="hljs-keyword">yield</span>, <span class="hljs-keyword">and</span> maintain long-term soil health.
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973525540/a1b55607-ae2f-4e57-8877-9429c147d7d3.png" alt="a1b55607-ae2f-4e57-8877-9429c147d7d3" class="image--center mx-auto" width="2048" height="1638" loading="lazy"></a></p>
<h3 id="heading-improving-crop-management-through-ai-enhanced-decision-support-systems"><strong>Improving Crop Management through AI-Enhanced Decision Support Systems</strong></h3>
<p>AI-enhanced decision support systems integrate various data sources to provide farmers with actionable insights. These systems analyze data from weather forecasts, soil sensors, and market trends to offer comprehensive advice on crop management.</p>
<p>For instance, a farmer in Europe growing wheat can use these systems to decide the optimal planting time, anticipate pest outbreaks, and estimate the best harvest period based on market prices. Such integrative approaches ensure that farmers can make knowledgeable decisions that balance productivity and profitability.</p>
<p>In the framework of smart greenhouses, AI algorithms control environmental conditions such as lighting, temperature, and humidity. An example is the use of AI in tomato greenhouses in the Netherlands, where machine learning algorithms autonomously adjust these parameters to create optimal growing conditions. This results in enhanced growth rates, improved fruit quality, and higher yields.</p>
<h4 id="heading-example-of-improving-crop-management-through-ai-enhanced-decision-support-systems"><strong>Example of improving crop management through AI-enhanced decision support systems</strong></h4>
<p><strong>Objective:</strong> Integrate an LLM into a decision support system to provide comprehensive advice based on multiple data sources, including weather forecasts, soil sensors, and market trends.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample data inputs</span>
data = {
    <span class="hljs-string">"weather_forecast"</span>: {
        <span class="hljs-string">"temperature"</span>: <span class="hljs-string">"25°C"</span>,
        <span class="hljs-string">"precipitation"</span>: <span class="hljs-string">"Low"</span>,
        <span class="hljs-string">"humidity"</span>: <span class="hljs-string">"60%"</span>,
        <span class="hljs-string">"wind_speed"</span>: <span class="hljs-string">"15 km/h"</span>
    },
    <span class="hljs-string">"soil_sensors"</span>: {
        <span class="hljs-string">"soil_moisture"</span>: <span class="hljs-string">"40%"</span>,
        <span class="hljs-string">"pH"</span>: <span class="hljs-string">"6.5"</span>,
        <span class="hljs-string">"nutrient_levels"</span>: {
            <span class="hljs-string">"nitrogen"</span>: <span class="hljs-string">"45 ppm"</span>,
            <span class="hljs-string">"phosphorus"</span>: <span class="hljs-string">"30 ppm"</span>,
            <span class="hljs-string">"potassium"</span>: <span class="hljs-string">"40 ppm"</span>
        }
    },
    <span class="hljs-string">"market_trends"</span>: {
        <span class="hljs-string">"wheat_price"</span>: <span class="hljs-string">"$200 per ton"</span>,
        <span class="hljs-string">"demand_growth"</span>: <span class="hljs-string">"5% annually"</span>
    },
    <span class="hljs-string">"crop_type"</span>: <span class="hljs-string">"wheat"</span>,
    <span class="hljs-string">"crop_stage"</span>: <span class="hljs-string">"flowering"</span>
}

<span class="hljs-comment"># Create a descriptive summary</span>
summary = (
    <span class="hljs-string">f"Weather Forecast: Temperature is <span class="hljs-subst">{data[<span class="hljs-string">'weather_forecast'</span>][<span class="hljs-string">'temperature'</span>]}</span>, "</span>
    <span class="hljs-string">f"precipitation is <span class="hljs-subst">{data[<span class="hljs-string">'weather_forecast'</span>][<span class="hljs-string">'precipitation'</span>]}</span>, "</span>
    <span class="hljs-string">f"humidity is <span class="hljs-subst">{data[<span class="hljs-string">'weather_forecast'</span>][<span class="hljs-string">'humidity'</span>]}</span>, and wind speed is <span class="hljs-subst">{data[<span class="hljs-string">'weather_forecast'</span>][<span class="hljs-string">'wind_speed'</span>]}</span>. "</span>
    <span class="hljs-string">f"Soil Sensors: Soil moisture is <span class="hljs-subst">{data[<span class="hljs-string">'soil_sensors'</span>][<span class="hljs-string">'soil_moisture'</span>]}</span>, pH is <span class="hljs-subst">{data[<span class="hljs-string">'soil_sensors'</span>][<span class="hljs-string">'pH'</span>]}</span>, "</span>
    <span class="hljs-string">f"nitrogen level is <span class="hljs-subst">{data[<span class="hljs-string">'soil_sensors'</span>][<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'nitrogen'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"phosphorus level is <span class="hljs-subst">{data[<span class="hljs-string">'soil_sensors'</span>][<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'phosphorus'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"and potassium level is <span class="hljs-subst">{data[<span class="hljs-string">'soil_sensors'</span>][<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'potassium'</span>]}</span> ppm. "</span>
    <span class="hljs-string">f"Market Trends: Wheat price is <span class="hljs-subst">{data[<span class="hljs-string">'market_trends'</span>][<span class="hljs-string">'wheat_price'</span>]}</span> with a demand growth of <span class="hljs-subst">{data[<span class="hljs-string">'market_trends'</span>][<span class="hljs-string">'demand_growth'</span>]}</span>. "</span>
    <span class="hljs-string">f"Crop Type: <span class="hljs-subst">{data[<span class="hljs-string">'crop_type'</span>]}</span> in the <span class="hljs-subst">{data[<span class="hljs-string">'crop_stage'</span>]}</span> stage."</span>
)

<span class="hljs-comment"># Use LLM to generate decision support advice</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an AI-powered agricultural decision support system."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Provide comprehensive advice based on the following data: <span class="hljs-subst">{summary}</span>"</span>}
    ]
)

advice = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(advice)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973576820/a2d9619d-da40-40c6-940f-da313bee150d.png" alt="A screenshot of Python code. It imports the  module and defines a dictionary called  with nested elements for weather forecast, soil sensors, market trends, crop type, and crop stage. A summary of these data points is created using formatted strings. The code then uses OpenAI's GPT-4 model to generate decision support advice based on the summary, with two messages: one defining the system's role and the other specifying the user's request. The response is printed as ." class="image--center mx-auto" width="2048" height="2420" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Comprehensive Crop Management Advice <span class="hljs-keyword">for</span> Wheat <span class="hljs-keyword">in</span> the Flowering Stage**

**Weather Considerations:**
- **Temperature (<span class="hljs-number">25</span>°C):** Optimal <span class="hljs-keyword">for</span> wheat flowering. Maintain current irrigation levels to support continued growth.
- **Precipitation (Low):** Monitor soil moisture closely. Consider implementing supplemental irrigation <span class="hljs-keyword">if</span> forecasts indicate prolonged dry periods.
- **Humidity (<span class="hljs-number">60</span>%):** Moderate humidity levels are conducive to wheat health. Ensure adequate air circulation to prevent fungal diseases.
- **Wind Speed (<span class="hljs-number">15</span> km/h):** Manage wind exposure to reduce the risk of lodging (plants falling over). Implement windbreaks <span class="hljs-keyword">if</span> necessary.

**Soil Management:**
- **Soil Moisture (<span class="hljs-number">40</span>%):** Adequate moisture levels. Continue regular irrigation to sustain optimal growth.
- **pH (<span class="hljs-number">6.5</span>):** Ideal pH <span class="hljs-keyword">for</span> wheat. No immediate adjustments needed.
- **Nutrient Levels:**
  - **Nitrogen (<span class="hljs-number">45</span> ppm):** Sufficient <span class="hljs-keyword">for</span> the flowering stage. Avoid over-fertilization to prevent lodging.
  - **Phosphorus (<span class="hljs-number">30</span> ppm):** Adequate. Continue monitoring to ensure availability <span class="hljs-keyword">for</span> grain development.
  - **Potassium (<span class="hljs-number">40</span> ppm):** Optimal levels. Maintains plant health <span class="hljs-keyword">and</span> stress resistance.

**Market Trends:**
- **Wheat Price ($<span class="hljs-number">200</span> per ton):** Favorable market conditions. Maximize <span class="hljs-keyword">yield</span> <span class="hljs-keyword">and</span> quality to capitalize on high prices.
- **Demand Growth (<span class="hljs-number">5</span>% annually):** Positive outlook. Invest <span class="hljs-keyword">in</span> strategies that enhance <span class="hljs-keyword">yield</span> <span class="hljs-keyword">and</span> sustainability to meet growing demand.

**Recommendations:**
<span class="hljs-number">1.</span> **Irrigation Management:**
   - Maintain current irrigation schedules.
   - Prepare <span class="hljs-keyword">for</span> potential supplemental irrigation <span class="hljs-keyword">if</span> dry conditions persist.

<span class="hljs-number">2.</span> **Pest <span class="hljs-keyword">and</span> Disease Control:**
   - With moderate humidity, remain vigilant <span class="hljs-keyword">for</span> signs of fungal diseases such <span class="hljs-keyword">as</span> powdery mildew.
   - Implement preventive measures, including appropriate fungicide applications <span class="hljs-keyword">if</span> necessary.

<span class="hljs-number">3.</span> **Nutrient Management:**
   - Continue <span class="hljs-keyword">with</span> balanced fertilization practices.
   - Avoid excess nitrogen to prevent lodging; consider applying a controlled-release fertilizer <span class="hljs-keyword">if</span> additional nutrients are needed.

<span class="hljs-number">4.</span> **Mechanical Practices:**
   - Assess fields <span class="hljs-keyword">for</span> signs of lodging <span class="hljs-keyword">and</span> take corrective actions <span class="hljs-keyword">if</span> required.
   - Ensure harvesting equipment <span class="hljs-keyword">is</span> calibrated to minimize grain loss <span class="hljs-keyword">and</span> maintain quality.

<span class="hljs-number">5.</span> **Harvest Planning:**
   - Monitor wheat maturity closely to determine the optimal harvest window.
   - Coordinate harvesting activities to align <span class="hljs-keyword">with</span> favorable market prices <span class="hljs-keyword">and</span> minimize weather-related risks.

<span class="hljs-number">6.</span> **Sustainability Practices:**
   - Implement crop rotation strategies to maintain soil health.
   - Utilize cover crops post-harvest to prevent soil erosion <span class="hljs-keyword">and</span> enhance organic matter content.

By adhering to these recommendations, you can optimize wheat <span class="hljs-keyword">yield</span> <span class="hljs-keyword">and</span> quality, capitalize on favorable market conditions, <span class="hljs-keyword">and</span> ensure sustainable farming practices <span class="hljs-keyword">for</span> future growth.
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973654006/a2de1b57-2884-47ad-9ce9-d5162f378342.png" alt="Code Example: &quot;Comprehensive Crop Management Advice for Wheat in the Flowering Stage&quot; detailing weather considerations, soil management, nutrient levels, market trends, and recommendations. The document emphasizes optimal temperature, precipitation, humidity, and wind speed, along with soil moisture, pH, nitrogen, phosphorus, and potassium levels. It includes market trends on wheat price and demand growth and lists recommendations for irrigation, pest and disease control, nutrient management, mechanical practices, harvest planning, and sustainability practices." class="image--center mx-auto" width="2048" height="2530" loading="lazy"></a></p>
<h3 id="heading-addressing-global-agricultural-challenges-with-ai"><strong>Addressing Global Agricultural Challenges with AI</strong></h3>
<p>AI technologies are not just limited to enhancing yields but are also pivotal in addressing global challenges such as climate change, food security, and sustainable resource management.</p>
<p>In regions prone to climate variability, AI models can predict and simulate different climate scenarios and recommend adaptive strategies for resilient farming. In doing so, AI helps secure food production against the changing climate.</p>
<p>For instance, in India, where farmers are heavily dependent on monsoon rains, AI-based systems can provide early warnings about deficient rainfalls. This allows farmers to switch to more drought-resistant crop varieties or alter their cropping patterns, thus safeguarding their livelihoods.</p>
<h4 id="heading-example-of-addressing-global-agricultural-challenges-with-ai"><strong>Example of addressing global agricultural challenges with AI</strong></h4>
<p><strong>Objective:</strong> Use an LLM to generate adaptive farming strategies based on climate predictions and other global challenges.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample climate data</span>
climate_data = {
    <span class="hljs-string">"region"</span>: <span class="hljs-string">"India"</span>,
    <span class="hljs-string">"climate_challenge"</span>: <span class="hljs-string">"Deficient monsoon rains"</span>,
    <span class="hljs-string">"current_crop"</span>: <span class="hljs-string">"rice"</span>,
    <span class="hljs-string">"alternative_crops"</span>: [<span class="hljs-string">"millet"</span>, <span class="hljs-string">"sorghum"</span>, <span class="hljs-string">"pulses"</span>],
    <span class="hljs-string">"forecast"</span>: <span class="hljs-string">"El Niño event expected to reduce rainfall by 30% in the upcoming season."</span>
}

<span class="hljs-comment"># Create a descriptive summary</span>
climate_summary = (
    <span class="hljs-string">f"Region: <span class="hljs-subst">{climate_data[<span class="hljs-string">'region'</span>]}</span>. "</span>
    <span class="hljs-string">f"Climate Challenge: <span class="hljs-subst">{climate_data[<span class="hljs-string">'climate_challenge'</span>]}</span>. "</span>
    <span class="hljs-string">f"Current Crop: <span class="hljs-subst">{climate_data[<span class="hljs-string">'current_crop'</span>]}</span>. "</span>
    <span class="hljs-string">f"Alternative Crops: <span class="hljs-subst">{<span class="hljs-string">', '</span>.join(climate_data[<span class="hljs-string">'alternative_crops'</span>])}</span>. "</span>
    <span class="hljs-string">f"Forecast: <span class="hljs-subst">{climate_data[<span class="hljs-string">'forecast'</span>]}</span>."</span>
)

<span class="hljs-comment"># Use LLM to recommend adaptive strategies</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an expert in sustainable agriculture and climate adaptation."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Given the following climate data, suggest adaptive farming strategies: <span class="hljs-subst">{climate_summary}</span>"</span>}
    ]
)

strategies = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(strategies)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973708961/9a076257-fbb0-458e-b82d-ddba36585cd5.png" alt="A code snippet demonstrating the use of OpenAI's API to analyze climate data and suggest adaptive farming strategies. The script includes a dictionary with sample climate data for India, constructs a descriptive summary, and sends a message to a language model to receive adaptive strategy recommendations. The output is printed at the end. - lunartech.ai" class="image--center mx-auto" width="2048" height="1600" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Adaptive Farming Strategies <span class="hljs-keyword">for</span> India Amidst Deficient Monsoon Rains**

**<span class="hljs-number">1.</span> Crop Diversification:**
   - **Shift to Drought-Resistant Crops:** Transition <span class="hljs-keyword">from</span> rice to more drought-tolerant crops such <span class="hljs-keyword">as</span> millet, sorghum, <span class="hljs-keyword">and</span> pulses. These crops require less water <span class="hljs-keyword">and</span> can thrive under reduced rainfall conditions.
   - **Intercropping:** Implement intercropping practices by planting multiple crop species simultaneously. This enhances resource utilization <span class="hljs-keyword">and</span> reduces the risk of total crop failure.

**<span class="hljs-number">2.</span> Water Management:**
   - **Rainwater Harvesting:** Construct rainwater harvesting systems to capture <span class="hljs-keyword">and</span> store residual rainfall during the monsoon <span class="hljs-keyword">for</span> use during dry periods.
   - **Drip Irrigation:** Adopt efficient irrigation techniques like drip <span class="hljs-keyword">or</span> sprinkler systems to minimize water wastage <span class="hljs-keyword">and</span> ensure targeted water delivery to crops.
   - **Soil Moisture Conservation:** Use mulching <span class="hljs-keyword">and</span> cover cropping to retain soil moisture <span class="hljs-keyword">and</span> reduce evaporation rates.

**<span class="hljs-number">3.</span> Soil Health Improvement:**
   - **Organic Amendments:** Incorporate organic matter such <span class="hljs-keyword">as</span> compost <span class="hljs-keyword">or</span> manure to improve soil structure, enhance water retention, <span class="hljs-keyword">and</span> increase nutrient availability.
   - **Conservation Tillage:** Practice conservation tillage methods to reduce soil erosion, maintain soil moisture, <span class="hljs-keyword">and</span> promote microbial activity.

**<span class="hljs-number">4.</span> Climate-Resilient Practices:**
   - **Agroforestry:** Integrate trees <span class="hljs-keyword">and</span> shrubs into agricultural landscapes to provide shade, reduce wind speed, <span class="hljs-keyword">and</span> improve microclimates <span class="hljs-keyword">for</span> crops.
   - **Weather Forecasting Utilization:** Leverage advanced weather forecasting tools to make informed decisions about planting, irrigation, <span class="hljs-keyword">and</span> harvesting schedules.

**<span class="hljs-number">5.</span> Financial <span class="hljs-keyword">and</span> Policy Support:**
   - **Subsidies <span class="hljs-keyword">for</span> Drought-Resistant Varieties:** Advocate <span class="hljs-keyword">for</span> government subsidies <span class="hljs-keyword">and</span> incentives <span class="hljs-keyword">for</span> farmers adopting drought-resistant crop varieties <span class="hljs-keyword">and</span> water-efficient technologies.
   - **Insurance Schemes:** Promote crop insurance schemes that protect farmers against losses due to climate-induced risks.

**<span class="hljs-number">6.</span> Community Engagement <span class="hljs-keyword">and</span> Education:**
   - **Training Programs:** Organize training sessions to educate farmers about climate-resilient farming techniques <span class="hljs-keyword">and</span> the benefits of crop diversification.
   - **Collaborative Platforms:** Foster community-based platforms <span class="hljs-keyword">for</span> knowledge sharing, enabling farmers to learn <span class="hljs-keyword">from</span> each othe<span class="hljs-string">r's experiences and adopt best practices.

**7. Technological Integration:**
   - **IoT and Sensors:** Deploy IoT devices and soil moisture sensors to monitor environmental conditions in real-time, allowing for timely interventions.
   - **AI-Driven Decision Support:** Utilize AI-powered tools to analyze climate data and provide personalized recommendations for crop management and resource allocation.

**8. Market Adaptation:**
   - **Value Addition:** Explore value-added products and alternative markets for drought-resistant crops to enhance profitability.
   - **Supply Chain Optimization:** Improve supply chain logistics to reduce post-harvest losses and ensure timely access to markets despite climatic challenges.

Implementing these adaptive strategies will help mitigate the adverse effects of deficient monsoon rains, ensure sustained agricultural productivity, and enhance the resilience of farming communities in India.</span>
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973753406/612f6612-6968-4e3d-971c-7271109733a7.png" alt="Adaptive Farming Strategies for India Amidst Deficient Monsoon Rains”. The document lists 8 strategies: 1) Crop Diversification, 2) Water Management, 3) Soil Health Improvement, 4) Climate-Resilient Practices, 5) Financial and Policy Support, 6) Community Engagement and Education, 7) Technological Integration, and 8) Market Adaptation. Each strategy includes several bullet points detailing specific methods, such as shifting to drought-resistant crops, constructing rainwater harvesting systems, incorporating organic soil amendments, promoting subsidies, and fostering community education. - lunartech.ai" class="image--center mx-auto" width="2048" height="2456" loading="lazy"></a></p>
<h3 id="heading-advancing-agricultural-research-through-ai"><strong>Advancing Agricultural Research through AI</strong></h3>
<p>AI is also making significant inroads into agricultural research. By fostering the development of new crop varieties, AI accelerates the breeding process. Machine learning models analyze vast datasets to identify traits associated with disease resistance, drought tolerance, and higher nutritional content. These insights expedite the breeding programs, leading to the development of superior crop varieties in record time.</p>
<p>For instance, in the quest to develop a rust-resistant wheat variety, researchers can use AI to sift through genetic data and pinpoint the genes responsible for resistance. This targeted approach not only saves time but also increases the likelihood of successful trait incorporation.</p>
<h4 id="heading-example-of-advancing-agricultural-research-through-ai"><strong>Example of advancing agricultural research through AI</strong></h4>
<p><strong>Objective:</strong> Employ an LLM to assist in analyzing genetic data for breeding programs aimed at developing disease-resistant or drought-tolerant crop varieties.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample genetic data summary</span>
genetic_data = {
    <span class="hljs-string">"crop"</span>: <span class="hljs-string">"wheat"</span>,
    <span class="hljs-string">"goal"</span>: <span class="hljs-string">"develop rust-resistant variety"</span>,
    <span class="hljs-string">"current_breeding_data"</span>: {
        <span class="hljs-string">"gene_X"</span>: <span class="hljs-string">"associated with leaf rust resistance"</span>,
        <span class="hljs-string">"gene_Y"</span>: <span class="hljs-string">"no significant association"</span>,
        <span class="hljs-string">"gene_Z"</span>: <span class="hljs-string">"linked to stem rust resistance"</span>
    },
    <span class="hljs-string">"existing_varieties"</span>: [<span class="hljs-string">"Variety_A"</span>, <span class="hljs-string">"Variety_B"</span>],
    <span class="hljs-string">"desired_traits"</span>: [<span class="hljs-string">"high yield"</span>, <span class="hljs-string">"drought tolerance"</span>]
}

<span class="hljs-comment"># Create a descriptive summary</span>
genetic_summary = (
    <span class="hljs-string">f"Crop: <span class="hljs-subst">{genetic_data[<span class="hljs-string">'crop'</span>]}</span>. "</span>
    <span class="hljs-string">f"Goal: <span class="hljs-subst">{genetic_data[<span class="hljs-string">'goal'</span>]}</span>. "</span>
    <span class="hljs-string">f"Current Breeding Data: <span class="hljs-subst">{<span class="hljs-string">', '</span>.join([<span class="hljs-string">f'<span class="hljs-subst">{gene}</span>: <span class="hljs-subst">{desc}</span>'</span> <span class="hljs-keyword">for</span> gene, desc <span class="hljs-keyword">in</span> genetic_data[<span class="hljs-string">'current_breeding_data'</span>].items()])}</span>. "</span>
    <span class="hljs-string">f"Existing Varieties: <span class="hljs-subst">{<span class="hljs-string">', '</span>.join(genetic_data[<span class="hljs-string">'existing_varieties'</span>])}</span>. "</span>
    <span class="hljs-string">f"Desired Traits: <span class="hljs-subst">{<span class="hljs-string">', '</span>.join(genetic_data[<span class="hljs-string">'desired_traits'</span>])}</span>."</span>
)

<span class="hljs-comment"># Use LLM to analyze genetic data and suggest next steps</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are a geneticist specializing in crop breeding."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Analyze the following genetic data and suggest next steps for developing a rust-resistant wheat variety with high yield and drought tolerance: <span class="hljs-subst">{genetic_summary}</span>"</span>}
    ]
)

analysis = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(analysis)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973828144/27878a82-fc8e-4b5c-9a7b-52939e65b238.png" alt="A screenshot of Python code that imports the OpenAI library and includes a genetic data summary for wheat. It defines variables and functions to create a descriptive summary of the genetic data, and uses an LLM (Large Language Model) to analyze the genetic data and suggest next steps for developing a rust-resistant wheat variety with high yield and drought tolerance. - lunartech.ai" class="image--center mx-auto" width="2048" height="1750" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Analysis <span class="hljs-keyword">and</span> Recommendations <span class="hljs-keyword">for</span> Developing a Rust-Resistant Wheat Variety <span class="hljs-keyword">with</span> High Yield <span class="hljs-keyword">and</span> Drought Tolerance**

**<span class="hljs-number">1.</span> Genetic Analysis:**
   - **Gene X:** Associated <span class="hljs-keyword">with</span> leaf rust resistance. This gene shows promise <span class="hljs-keyword">for</span> enhancing the plant<span class="hljs-string">'s ability to withstand foliar rust infections.
   - **Gene Y:** No significant association with rust resistance. It may be deprioritized in the breeding program.
   - **Gene Z:** Linked to stem rust resistance. Incorporating this gene can provide comprehensive rust resistance, targeting both leaf and stem infections.

**2. Breeding Strategy:**
   - **Marker-Assisted Selection (MAS):** Utilize molecular markers linked to Gene X and Gene Z to facilitate the selection of individuals carrying these resistance genes. This approach accelerates the breeding process by enabling the identification of desired traits at the seedling stage.
   - **Pyramiding Resistance Genes:** Combine Gene X and Gene Z within a single genotype to ensure broad-spectrum rust resistance. This strategy reduces the likelihood of rust pathogens overcoming resistance through mutation.
   - **Incorporate Desired Traits:**
     - **High Yield:** Select parent lines known for their high-yield potential. Ensure that these lines are compatible with the rust-resistant varieties to maintain yield performance.
     - **Drought Tolerance:** Integrate genes or quantitative trait loci (QTLs) associated with drought tolerance. This can be achieved through traditional breeding methods or by employing genomic selection techniques.

**3. Crossbreeding Plan:**
   - **Parent Selection:** Choose existing varieties (e.g., Variety_A and Variety_B) that exhibit high yield and possess either Gene X or Gene Z.
   - **Hybridization:** Perform crosses between these parent lines to combine rust resistance with high yield traits.
   - **Progeny Evaluation:** Assess the offspring for rust resistance, yield performance, and drought tolerance through phenotypic screening and molecular assays.

**4. Genomic Tools and Techniques:**
   - **Genomic Selection:** Implement genomic selection models to predict the performance of breeding lines based on their genetic makeup. This enhances the accuracy of selecting superior genotypes.
   - **CRISPR-Cas9 Gene Editing:** Consider utilizing gene editing technologies to precisely insert or enhance Gene X and Gene Z in elite wheat varieties, reducing the time required for conventional breeding.

**5. Field Trials and Validation:**
   - **Multi-Location Trials:** Conduct field trials across different environments to evaluate the stability and effectiveness of rust resistance and drought tolerance under varying conditions.
   - **Pathogen Monitoring:** Continuously monitor rust pathogen populations to ensure that the resistance conferred by Gene X and Gene Z remains effective over time.

**6. Collaboration and Data Sharing:**
   - **Research Partnerships:** Collaborate with research institutions and agricultural organizations to share genetic data, breeding lines, and best practices.
   - **Data Management:** Maintain a comprehensive database of genetic markers, phenotypic traits, and breeding outcomes to inform future breeding decisions and track progress.

**7. Sustainability and Farmer Adoption:**
   - **Seed Distribution:** Develop a strategy for the distribution of the new rust-resistant, high-yield, and drought-tolerant wheat varieties to farmers.
   - **Training and Support:** Provide training to farmers on the benefits and cultivation practices of the new varieties to ensure successful adoption and maximize impact.

**Conclusion:**
By integrating Gene X and Gene Z through marker-assisted selection and genomic tools, and by incorporating high yield and drought tolerance traits, the breeding program can successfully develop a robust wheat variety. This variety will not only resist rust pathogens but also thrive under drought conditions, ensuring food security and enhancing agricultural sustainability.</span>
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725973891998/b8e760e4-6ae7-471e-9024-9cd7ab46a737.png" alt="Analysis and Recommendations for Developing a Rust-Resistant Wheat Variety with High Yield and Drought Tolerance. The document outlines various sections, including Genetic Analysis, Breeding Strategy, Crossbreeding Plan, Genomic Tools and Techniques, Field Trials and Validation, Collaboration and Data Sharing, and Sustainability and Farmer Adoption. The conclusion emphasizes the integration of specific genes and advanced techniques to create a robust wheat variety that resists rust pathogens and thrives under drought conditions." class="image--center mx-auto" width="2048" height="2716" loading="lazy"></a></p>
<p>These examples demonstrate how Large Language Models (LLMs) like OpenAI's GPT-4 can be integrated into various agricultural applications to enhance decision-making, provide actionable insights, and support sustainable farming practices.</p>
<p>Just a quick note: make sure you handle API keys securely and comply with OpenAI's usage policies when implementing these solutions.</p>
<p>These strategies represent a paradigm shift towards more resilient, efficient, and sustainable farming practices. By enabling predictive analytics, precision agriculture, and enhanced soil management, AI empowers farmers to make smarter decisions, optimize resource use, and achieve higher yields. T</p>
<h2 id="heading-chapter-2-how-to-enhance-crop-yields-and-productivity">Chapter 2: How to Enhance Crop Yields and Productivity</h2>
<p>Modern agriculture faces a plethora of challenges, including climate variability, resource scarcity, and the need for increased productivity. To navigate these complexities, contemporary farmers are increasingly turning to cutting-edge soil mapping techniques facilitated by advancements in computer vision and machine learning.</p>
<p>Soil mapping involves the systematic collection, analysis, and visualization of soil properties across agricultural fields. Incorporating technologies like AI, farmers can now produce high-resolution soil maps, revealing intricate details about soil quality, moisture levels, and nutrient content.</p>
<p>This knowledge is foundational for precision agriculture, a practice that emphasizes resource efficiency and sustainability by tailoring farming inputs to the specific needs of each soil type.</p>
<p>To integrate Large Language Models (LLMs) into the precision agriculture domain, we can leverage LLMs for generating insights, recommendations, and explanations based on soil maps, crop health data, and sustainability metrics.</p>
<p>As above, I’ll include code snippets for each section in this chapter where an LLM, such as GPT-4, is used to enhance efficiency, improve crop health, and promote sustainable farming practices.</p>
<p>Ensure that you have the <code>openai</code> Python package installed and have set up your API key properly before running the following code.</p>
<pre><code class="lang-bash">pip install openai
</code></pre>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai
<span class="hljs-keyword">import</span> os

<span class="hljs-comment"># Set your OpenAI API key</span>
openai.api_key = os.getenv(<span class="hljs-string">"OPENAI_API_KEY"</span>)
</code></pre>
<p>Alright, now we can dive into learning about the advantages and challenges of precision agriculture – with our code examples to guide us.</p>
<h3 id="heading-the-advantages-of-precision-agriculture"><strong>The Advantages of Precision Agriculture</strong></h3>
<p><strong>1. Enhanced Efficiency</strong></p>
<p>The central tenet of precision agriculture is maximizing efficiency. By using soil maps, farmers can precisely calibrate the application of water, fertilizers, and pesticides.</p>
<p>Traditional farming methods often involve uniform applications across an entire field, leading to overuse in some areas and underuse in others. Soil mapping helps farmers identify zones with varying needs, ensuring each section of the field receives the optimal amount of inputs.</p>
<p>For instance, an area identified as nutrient-rich may require minimal fertilization, whereas nutrient-poor zones can be targeted with customized fertilizer applications. This targeted approach conserves resources while enhancing overall farm productivity.</p>
<p>Consider a wheat farm that used traditional uniform fertilization methods. By switching to precision agriculture guided by detailed soil maps, the farmer could reduce fertilizer use by, say, 20% while increasing yield by 15%. This not only cuts costs but also minimizes environmental impact, showcasing a win-win scenario both economically and ecologically.</p>
<p>Now, let’s look at a code example to put this into practice.</p>
<p><strong>Objective:</strong> Use LLMs to generate optimized fertilization schedules based on soil maps, minimizing resource usage and enhancing farm productivity.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample soil data for a wheat farm (soil nutrient levels in different zones)</span>
soil_map_data = {
    <span class="hljs-string">"Zone_A"</span>: {<span class="hljs-string">"nutrients"</span>: <span class="hljs-string">"high"</span>, <span class="hljs-string">"water_requirement"</span>: <span class="hljs-string">"low"</span>, <span class="hljs-string">"fertilizer_recommendation"</span>: <span class="hljs-string">"minimal"</span>},
    <span class="hljs-string">"Zone_B"</span>: {<span class="hljs-string">"nutrients"</span>: <span class="hljs-string">"low"</span>, <span class="hljs-string">"water_requirement"</span>: <span class="hljs-string">"medium"</span>, <span class="hljs-string">"fertilizer_recommendation"</span>: <span class="hljs-string">"high"</span>},
    <span class="hljs-string">"Zone_C"</span>: {<span class="hljs-string">"nutrients"</span>: <span class="hljs-string">"medium"</span>, <span class="hljs-string">"water_requirement"</span>: <span class="hljs-string">"high"</span>, <span class="hljs-string">"fertilizer_recommendation"</span>: <span class="hljs-string">"moderate"</span>}
}

<span class="hljs-comment"># Convert soil data into a descriptive text</span>
soil_description = (
    <span class="hljs-string">f"Zone A has high nutrients and low water requirement. Zone B has low nutrients and medium water requirement. "</span>
    <span class="hljs-string">f"Zone C has medium nutrients and high water requirement."</span>
)

<span class="hljs-comment"># Use LLM to generate a targeted fertilization plan based on soil map data</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an agricultural expert specializing in precision farming."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following soil map data, create an optimized fertilization plan: <span class="hljs-subst">{soil_description}</span>"</span>}
    ]
)

fertilization_plan = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(fertilization_plan)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725974502369/3614afbe-c6e2-44b6-a4dc-18b33928e3eb.png" alt="A screenshot displaying a Python script that uses the OpenAI API to generate a fertilization plan based on soil map data for a wheat farm. The script includes sample data for nutrients, water requirements, and fertilizer recommendations for different zones of the farm. The script converts soil data into descriptive text and uses a language model to create a targeted fertilization plan. The response and final fertilization plan are printed out. - lunartech.ai" class="image--center mx-auto" width="2048" height="1526" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Optimized Fertilization Plan:**

- **Zone A:** Since nutrients are high <span class="hljs-keyword">and</span> water requirements are low, apply minimal fertilizer (around <span class="hljs-number">10</span>% of the recommended rate) <span class="hljs-keyword">and</span> avoid excessive watering. Focus on maintaining nutrient levels <span class="hljs-keyword">and</span> monitor soil moisture regularly.

- **Zone B:** Nutrients are low, so apply a high dose of nitrogen-based fertilizer to boost soil fertility. Watering should be done at medium levels to ensure proper nutrient absorption. Use <span class="hljs-number">80</span><span class="hljs-number">-90</span>% of the recommended fertilizer rate <span class="hljs-keyword">for</span> nutrient-poor soils.

- **Zone C:** Apply a moderate amount of fertilizer (<span class="hljs-number">50</span><span class="hljs-number">-60</span>% of the recommended rate) to ensure nutrient balance. Since water requirements are high, implement a regular irrigation schedule to maintain soil moisture at optimal levels.

By applying this plan, fertilizer usage can be reduced by <span class="hljs-number">20</span>%, <span class="hljs-keyword">while</span> maximizing crop <span class="hljs-keyword">yield</span> <span class="hljs-keyword">and</span> minimizing environmental impact.
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725974544486/37309a20-eb92-476b-839e-4521c8618986.png" alt="Optimized Fertilization Plan with three zones:- Zone A: High nutrients, low water requirement; apply 10% of recommended fertilizer, avoid excessive watering.- Zone B: Low nutrients; apply 80-90% nitrogen-based fertilizer, medium watering.- Zone C: Moderate fertilizer (50-60%); high water requirement, regular irrigation.Applying this plan can reduce fertilizer use by 20%, while maximizing crop yield and minimizing environmental impact. - lunartech.ai" class="image--center mx-auto" width="2048" height="968" loading="lazy"></a></p>
<p><strong>2. Improved Crop Health</strong></p>
<p>Soil is the lifeblood of crops, and its condition directly affects plant health. Detailed soil mapping enables farmers to monitor and address issues proactively.</p>
<p>For instance, if a specific area within a field shows signs of nutrient deficiency or excess salinity, remedial measures can be taken immediately. This proactive stance prevents problems before they escalate, ensuring that crops grow in optimal conditions throughout their life cycle.</p>
<p>In a vineyard, soil mapping may reveal high salinity levels in a particular section, which could adversely affect grape quality. By identifying and treating these areas with appropriate soil amendments, the vineyard can improve grape quality and yield, leading to better wine production and higher profits.</p>
<p>Now let’s look at a code example to help show how proactive soil monitoring can actually improve crop health.</p>
<p><strong>Objective:</strong> Utilize an LLM to provide recommendations for addressing soil salinity and nutrient deficiencies based on real-time soil health data.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample data from soil monitoring in a vineyard</span>
soil_health_data = {
    <span class="hljs-string">"Zone_A"</span>: {<span class="hljs-string">"salinity"</span>: <span class="hljs-string">"high"</span>, <span class="hljs-string">"nutrient_deficiency"</span>: <span class="hljs-string">"none"</span>},
    <span class="hljs-string">"Zone_B"</span>: {<span class="hljs-string">"salinity"</span>: <span class="hljs-string">"normal"</span>, <span class="hljs-string">"nutrient_deficiency"</span>: <span class="hljs-string">"low phosphorus"</span>},
    <span class="hljs-string">"Zone_C"</span>: {<span class="hljs-string">"salinity"</span>: <span class="hljs-string">"normal"</span>, <span class="hljs-string">"nutrient_deficiency"</span>: <span class="hljs-string">"low nitrogen"</span>}
}

<span class="hljs-comment"># Convert soil health data into a descriptive text</span>
soil_health_description = (
    <span class="hljs-string">f"Zone A has high salinity but no nutrient deficiency. "</span>
    <span class="hljs-string">f"Zone B has normal salinity but a low phosphorus deficiency. "</span>
    <span class="hljs-string">f"Zone C has normal salinity but a low nitrogen deficiency."</span>
)

<span class="hljs-comment"># Use LLM to generate recommendations for improving crop health based on soil data</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an expert in soil health and crop management."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following soil health data, provide recommendations to improve crop health: <span class="hljs-subst">{soil_health_description}</span>"</span>}
    ]
)

crop_health_recommendations = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(crop_health_recommendations)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725974608395/66dee35f-e422-4b1b-bf00-fde058bdb7e4.png" alt="A screenshot of Python code using the OpenAI API. The code imports the OpenAI library, defines sample soil health data for three zones in a vineyard, converts the data into descriptive text, and then uses an OpenAI language model (GPT-4) to generate crop health recommendations based on the soil data. Finally, it prints the generated recommendations." class="image--center mx-auto" width="2048" height="1414" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Crop Health Recommendations:**

- **Zone A (High Salinity):** Implement soil amendments, such <span class="hljs-keyword">as</span> gypsum, to reduce salinity levels. Ensure that irrigation water <span class="hljs-keyword">is</span> low <span class="hljs-keyword">in</span> salt content to prevent further salinity buildup. Consider deep leaching to flush salts <span class="hljs-keyword">from</span> the root zone.

- **Zone B (Low Phosphorus):** Apply phosphorus-rich fertilizers, such <span class="hljs-keyword">as</span> superphosphate <span class="hljs-keyword">or</span> bone meal, to address the deficiency. Focus on early applications during the growing season to promote root development.

- **Zone C (Low Nitrogen):** Apply a nitrogen-rich fertilizer, such <span class="hljs-keyword">as</span> urea <span class="hljs-keyword">or</span> ammonium nitrate, to boost nitrogen levels. Ensure that applications are spaced out to prevent nitrogen leaching <span class="hljs-keyword">and</span> optimize absorption by the crops.

These actions will enhance grape quality <span class="hljs-keyword">and</span> overall crop <span class="hljs-keyword">yield</span>, improving profitability <span class="hljs-keyword">and</span> sustainability.
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725974652312/d47380e1-7654-4d15-896e-875e4a759347.png" alt="Screenshot of code recommendations for improving crop health in three zones:1. Zone A (High Salinity): Implement soil amendments and ensure low-salt irrigation water.2. Zone B (Low Phosphorus): Apply phosphorus-rich fertilizers for root development.3. Zone C (Low Nitrogen): Apply nitrogen-rich fertilizers and ensure spaced applications.The measures aim to enhance grape quality, crop yield, profitability, and sustainability. - lunartech.ai" class="image--center mx-auto" width="2048" height="968" loading="lazy"></a></p>
<p><strong>3. Sustainable Farming Practices</strong></p>
<p>Precision agriculture is synonymous with sustainability. Traditional farming methods often involve excessive use of water, fertilizers, and pesticides, contributing to resource depletion and environmental degradation.</p>
<p>Precise soil mapping helps in reducing these inputs to only what is necessary, fostering sustainable agricultural practices. This not only conserves resources but also minimizes the ecological footprint of farming activities.</p>
<p>For example, a rice grower in a water-scarce region can use soil moisture maps to implement a precise irrigation schedule. This approach could reduce water use by as much as 30%, conserve groundwater resources, and enhance crop yield by ensuring consistent soil moisture levels.</p>
<p>Let’s go through a code example that shows how precision irrigation can be implemented using AI tools.</p>
<p><strong>Objective:</strong> Leverage an LLM to generate irrigation schedules based on soil moisture maps for sustainable water use.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample soil moisture data for a rice grower</span>
soil_moisture_map = {
    <span class="hljs-string">"Field_A"</span>: {<span class="hljs-string">"moisture_level"</span>: <span class="hljs-string">"high"</span>, <span class="hljs-string">"irrigation_requirement"</span>: <span class="hljs-string">"low"</span>},
    <span class="hljs-string">"Field_B"</span>: {<span class="hljs-string">"moisture_level"</span>: <span class="hljs-string">"moderate"</span>, <span class="hljs-string">"irrigation_requirement"</span>: <span class="hljs-string">"medium"</span>},
    <span class="hljs-string">"Field_C"</span>: {<span class="hljs-string">"moisture_level"</span>: <span class="hljs-string">"low"</span>, <span class="hljs-string">"irrigation_requirement"</span>: <span class="hljs-string">"high"</span>}
}

<span class="hljs-comment"># Convert soil moisture data into a descriptive text</span>
moisture_description = (
    <span class="hljs-string">f"Field A has high soil moisture and low irrigation requirements. "</span>
    <span class="hljs-string">f"Field B has moderate soil moisture and medium irrigation requirements. "</span>
    <span class="hljs-string">f"Field C has low soil moisture and high irrigation requirements."</span>
)

<span class="hljs-comment"># Use LLM to generate a water-saving irrigation schedule</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an expert in sustainable farming and irrigation management."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following soil moisture data, generate an efficient irrigation schedule: <span class="hljs-subst">{moisture_description}</span>"</span>}
    ]
)

irrigation_schedule = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(irrigation_schedule)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725974712238/717a86a3-5058-4d88-9b48-5fe19ffe5c45.png" alt="A code snippet using the OpenAI API to generate a water-saving irrigation schedule for a rice grower based on soil moisture data. The code includes sample soil moisture data for three fields, conversion of this data into descriptive text, and usage of the GPT-4 language model to create an irrigation schedule. The irrigation schedule is then printed. - lunartech.ai" class="image--center mx-auto" width="2048" height="1452" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Water-Efficient Irrigation Schedule:**

- **Field A (High Moisture):** No immediate irrigation <span class="hljs-keyword">is</span> needed. Monitor moisture levels over the next <span class="hljs-number">7</span><span class="hljs-number">-10</span> days <span class="hljs-keyword">and</span> consider irrigation only <span class="hljs-keyword">if</span> the moisture level drops below optimal thresholds. Focus on water conservation <span class="hljs-keyword">in</span> this zone.

- **Field B (Moderate Moisture):** Irrigate this field at medium intensity (<span class="hljs-number">50</span><span class="hljs-number">-60</span>% of the standard rate) to maintain consistent soil moisture. Irrigation can be scheduled every <span class="hljs-number">3</span><span class="hljs-number">-4</span> days based on weather conditions.

- **Field C (Low Moisture):** Prioritize this field <span class="hljs-keyword">for</span> irrigation <span class="hljs-keyword">with</span> high-intensity watering (<span class="hljs-number">80</span><span class="hljs-number">-90</span>% of the standard rate). Schedule irrigation every <span class="hljs-number">2</span> days to ensure sufficient moisture levels, especially during the critical growth phase.

By following this schedule, water usage can be reduced by <span class="hljs-number">30</span>%, conserving resources <span class="hljs-keyword">while</span> ensuring optimal soil moisture <span class="hljs-keyword">for</span> crop growth.
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725974755908/d9c1d481-296c-41e2-be43-a9891f95e677.png" alt="A screenshot displaying a &quot;Water-Efficient Irrigation Schedule&quot; with three field categories: Field A (High Moisture), Field B (Moderate Moisture), and Field C (Low Moisture). Each category has specific irrigation guidelines aimed at conserving water and ensuring optimal soil moisture for crop growth. Following this schedule can reduce water usage by 30%. - lunartech.ai" class="image--center mx-auto" width="2048" height="968" loading="lazy"></a></p>
<p><strong>4. Data-Driven Decision Making</strong></p>
<p>The integration of AI in soil mapping transforms raw data into actionable insights. AI-powered models can analyze soil characteristics and predict how different crops will respond to specific conditions.</p>
<p>This predictive capability empowers farmers to make informed decisions that optimize productivity and profitability. It also allows for real-time monitoring and adjustments, ensuring that farming practices evolve dynamically based on current data.</p>
<p>And lastly, let’s see how combining LLMs and precision agriculture can help you make data-driven decisions.</p>
<p><strong>Objective:</strong> Integrate an LLM into a decision-making system that takes into account various precision agriculture metrics (soil health, moisture, nutrients) to suggest comprehensive farming strategies.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Comprehensive data for a wheat farm</span>
precision_agriculture_data = {
    <span class="hljs-string">"soil_nutrients"</span>: {
        <span class="hljs-string">"Zone_A"</span>: {<span class="hljs-string">"nitrogen"</span>: <span class="hljs-string">"high"</span>, <span class="hljs-string">"phosphorus"</span>: <span class="hljs-string">"moderate"</span>, <span class="hljs-string">"potassium"</span>: <span class="hljs-string">"low"</span>},
        <span class="hljs-string">"Zone_B"</span>: {<span class="hljs-string">"nitrogen"</span>: <span class="hljs-string">"low"</span>, <span class="hljs-string">"phosphorus"</span>: <span class="hljs-string">"high"</span>, <span class="hljs-string">"potassium"</span>: <span class="hljs-string">"moderate"</span>},
        <span class="hljs-string">"Zone_C"</span>: {<span class="hljs-string">"nitrogen"</span>: <span class="hljs-string">"moderate"</span>, <span class="hljs-string">"phosphorus"</span>: <span class="hljs-string">"low"</span>, <span class="hljs-string">"potassium"</span>: <span class="hljs-string">"high"</span>}
    },
    <span class="hljs-string">"moisture_levels"</span>: {
        <span class="hljs-string">"Zone_A"</span>: <span class="hljs-string">"low"</span>,
        <span class="hljs-string">"Zone_B"</span>: <span class="hljs-string">"moderate"</span>,
        <span class="hljs-string">"Zone_C"</span>: <span class="hljs-string">"high"</span>
    },
    <span class="hljs-string">"crop_type"</span>: <span class="hljs-string">"wheat"</span>
}

<span class="hljs-comment"># Convert precision agriculture data into a descriptive text</span>
precision_data_description = (
    <span class="hljs-string">f"Zone A has high nitrogen, moderate phosphorus, and low potassium with low moisture levels. "</span>
    <span class="hljs-string">f"Zone B has low nitrogen, high phosphorus, and moderate potassium with moderate moisture levels. "</span>
    <span class="hljs-string">f"Zone C has moderate nitrogen, low phosphorus, and high potassium with high moisture levels."</span>
)

<span class="hljs-comment"># Use LLM to generate a comprehensive farming strategy</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an agricultural consultant specializing in precision farming."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following precision agriculture data, provide a comprehensive farming strategy: <span class="hljs-subst">{precision_data_description}</span>"</span>}
    ]
)

farming_strategy = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(f

arming_strategy)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725974815071/877eebf6-a3fa-41b3-adcc-b755a6f6d1b2.png" alt="A screenshot of a Python script using the OpenAI API to generate a comprehensive farming strategy based on precision agriculture data. The script includes definitions for soil nutrients, moisture levels, and crop type for different zones, converts the data into descriptive text, and uses the OpenAI GPT-4 model to create and print the farming strategy. - lunartech.ai" class="image--center mx-auto" width="2048" height="1824" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Comprehensive Farming Strategy <span class="hljs-keyword">for</span> Wheat:**

- **Zone A:** 
  - **Nutrient Management:** Since nitrogen levels are high <span class="hljs-keyword">and</span> potassium <span class="hljs-keyword">is</span> low, apply a potassium-rich fertilizer (e.g., potassium sulfate) to balance nutrient availability. Avoid applying additional nitrogen to prevent over-fertilization.
  - **Moisture Management:** Moisture levels are low, so prioritize irrigation <span class="hljs-keyword">in</span> this zone. Implement drip irrigation to target water delivery effectively without wastage.

- **Zone B:** 
  - **Nutrient Management:** Low nitrogen levels suggest the need <span class="hljs-keyword">for</span> a nitrogen-based fertilizer (e.g., urea <span class="hljs-keyword">or</span> ammonium nitrate). Since phosphorus <span class="hljs-keyword">is</span> already high, avoid adding phosphorus-rich fertilizers. Focus on nitrogen supplementation <span class="hljs-keyword">for</span> optimal growth.
  - **Moisture Management:** Moderate moisture levels are sufficient. Irrigate at a moderate intensity (<span class="hljs-number">50</span><span class="hljs-number">-60</span>% of the standard rate) every <span class="hljs-number">3</span><span class="hljs-number">-4</span> days.

- **Zone C:** 
  - **Nutrient Management:** Moderate nitrogen levels are acceptable, but low phosphorus levels require attention. Apply a phosphorus-rich fertilizer (e.g., superphosphate) to boost phosphorus content. Maintain potassium levels by applying a balanced fertilizer <span class="hljs-keyword">as</span> needed.
  - **Moisture Management:** Since moisture levels are high, irrigation can be minimized <span class="hljs-keyword">or</span> delayed. Monitor soil moisture closely <span class="hljs-keyword">and</span> irrigate only <span class="hljs-keyword">if</span> levels drop below optimal thresholds.

This strategy will optimize nutrient management, reduce water usage, <span class="hljs-keyword">and</span> ensure higher wheat yields across all zones. By implementing targeted interventions, you can increase crop productivity <span class="hljs-keyword">while</span> minimizing resource inputs.
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725974862501/1b5a176f-e18d-4a76-b226-bb07873acc04.png" alt="Comprehensive Farming Strategy for Wheat. The document outlines nutrient and moisture management strategies for three zones (A, B, and C) to optimize wheat production. Each zone's strategy includes specific fertilizer recommendations and irrigation practices based on nitrogen, potassium, and phosphorus levels. The goal is to enhance nutrient management, reduce water usage, and improve crop productivity by implementing targeted interventions. - lunartech.ai" class="image--center mx-auto" width="2048" height="1340" loading="lazy"></a></p>
<p>In these examples, you saw how LLMs can help you analyze data from precision agriculture, provide actionable recommendations, and generate optimized strategies for enhancing efficiency, improving crop health, and promoting sustainable practices.</p>
<p>LLMs can handle a variety of agricultural data inputs and deliver personalized insights that help farmers make informed decisions, optimizing their farming processes.</p>
<h3 id="heading-challenges-of-precision-agriculture"><strong>Challenges of Precision Agriculture</strong></h3>
<p><strong>1. The Initial Investment</strong></p>
<p>One of the primary challenges in adopting precision agriculture is the significant initial investment. Advanced soil mapping technologies, AI models, and precision farming equipment require substantial capital outlay. But the long-term benefits – heightened crop yields, reduced input costs, and sustainable farming practices – often justify this upfront expenditure.</p>
<p>Financial aid and subsidies from governments and agricultural bodies can also mitigate the initial costs, making these technologies more accessible to small and medium-sized farmers.</p>
<p>As a solution, financial planning and incremental investments can ease the transition to precision agriculture. Farmers can start with essential technologies and gradually expand their toolkit as the initial benefits begin to materialize, thereby reducing financial strain.</p>
<p><strong>2. Data Accuracy and Security</strong></p>
<p>The effectiveness of AI-driven soil mapping hinges on the accuracy and security of data. Inaccurate data can lead to poor decision-making, negating the benefits of precision agriculture. Also, data privacy concerns and the potential for cyber threats necessitate robust security measures.</p>
<p>To combat these challenges, try implementing rigorous data validation protocols. These can help ensure the accuracy of collected data. Also, employ advanced cybersecurity measures that protect against data breaches, thereby maintaining the integrity and confidentiality of valuable agricultural data.</p>
<h3 id="heading-soil-mapping-ai-for-the-win">Soil Mapping + AI For the Win</h3>
<p>Soil mapping techniques, augmented by AI and machine learning, are revolutionizing precision agriculture. By providing detailed insights into soil conditions, these technologies enable farmers to enhance efficiency, improve crop health, adopt sustainable practices, and make informed decisions.</p>
<p>Despite challenges such as initial investment and data security, the long-term benefits of precision agriculture are profound, promising increased crop yields and reduced environmental impact.</p>
<p>As the agricultural sector continues to innovate, soil mapping will undoubtedly play a pivotal role in shaping the future of farming, fostering a more productive and sustainable agricultural landscape for generations to come.</p>
<h2 id="heading-chapter-3-labor-optimization-solutions-through-ai-in-agriculture">Chapter 3: Labor Optimization Solutions Through AI in Agriculture</h2>
<p>Agricultural enterprises worldwide are increasingly leveraging Artificial Intelligence (AI) to address one of the most pressing challenges: labor shortages. AI technologies offer transformative solutions that enhance efficiency and optimize various operations within the sector.</p>
<p>By examining AI's role in enhancing farm labor management, precision agriculture, and AI-driven robotics and automation, we can appreciate its profound impact on overcoming workforce scarcity.</p>
<h3 id="heading-enhanced-farm-labor-management"><strong>Enhanced Farm Labor Management</strong></h3>
<p>Farm labor management has traditionally been resource-intensive, often hindered by inefficiencies resulting from manual planning and unpredictable variables like weather.</p>
<p>AI models integrated into farm management software revolutionize this space by enabling highly precise resource allocation and task assignment. Machine learning algorithms analyze extensive datasets encompassing soil conditions, weather patterns, crop growth stages, and historical farm performance to devise actionable insights.</p>
<p>For example, AI can identify the optimal times for planting, irrigating, and harvesting by processing current and forecasting data. This predictive capability ensures farming activities are synchronized with peak resource availability, minimizing labor bottlenecks. This means that farms can plan their workforce requirements more effectively, reducing downtime and enhancing overall productivity.</p>
<p>But AI's potential extends beyond mere task scheduling. It supports decision-making processes through real-time feedback mechanisms, allowing farm managers to adjust strategies dynamically. For instance, if an unexpected weather change is detected, AI can prompt adjustments to irrigation schedules or suggest protective measures, thereby safeguarding crops and ensuring labor is utilized efficiently.</p>
<p><strong>Let’s look at an example of how you’d put this into practice.</strong></p>
<p><strong>Objective:</strong> Utilize an LLM to generate dynamic task scheduling for farm labor management based on weather, soil, and crop growth data. The system adapts in real-time to changing environmental conditions.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai
<span class="hljs-keyword">import</span> datetime

<span class="hljs-comment"># Sample environmental data (weather, soil moisture, crop growth)</span>
environmental_data = {
    <span class="hljs-string">"weather_forecast"</span>: {
        <span class="hljs-string">"today"</span>: {<span class="hljs-string">"temp"</span>: <span class="hljs-number">28</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">20</span>, <span class="hljs-string">"wind_speed"</span>: <span class="hljs-number">10</span>},
        <span class="hljs-string">"tomorrow"</span>: {<span class="hljs-string">"temp"</span>: <span class="hljs-number">30</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">50</span>, <span class="hljs-string">"wind_speed"</span>: <span class="hljs-number">5</span>}
    },
    <span class="hljs-string">"soil_conditions"</span>: {
        <span class="hljs-string">"moisture_level"</span>: <span class="hljs-number">60</span>,  <span class="hljs-comment"># percentage</span>
        <span class="hljs-string">"fertility_level"</span>: <span class="hljs-string">"high"</span>
    },
    <span class="hljs-string">"crop_stage"</span>: <span class="hljs-string">"vegetative"</span>
}

<span class="hljs-comment"># Convert environmental data into a readable description</span>
environment_description = (
    <span class="hljs-string">f"Today's weather forecast: temperature <span class="hljs-subst">{environmental_data[<span class="hljs-string">'weather_forecast'</span>][<span class="hljs-string">'today'</span>][<span class="hljs-string">'temp'</span>]}</span>°C, "</span>
    <span class="hljs-string">f"precipitation <span class="hljs-subst">{environmental_data[<span class="hljs-string">'weather_forecast'</span>][<span class="hljs-string">'today'</span>][<span class="hljs-string">'precipitation'</span>]}</span>mm, wind speed <span class="hljs-subst">{environmental_data[<span class="hljs-string">'weather_forecast'</span>][<span class="hljs-string">'today'</span>][<span class="hljs-string">'wind_speed'</span>]}</span> km/h. "</span>
    <span class="hljs-string">f"Soil moisture level is <span class="hljs-subst">{environmental_data[<span class="hljs-string">'soil_conditions'</span>][<span class="hljs-string">'moisture_level'</span>]}</span>% and fertility level is <span class="hljs-subst">{environmental_data[<span class="hljs-string">'soil_conditions'</span>][<span class="hljs-string">'fertility_level'</span>]}</span>. "</span>
    <span class="hljs-string">f"The crop is currently in the <span class="hljs-subst">{environmental_data[<span class="hljs-string">'crop_stage'</span>]}</span> stage."</span>
)

<span class="hljs-comment"># Use LLM to generate a farm labor schedule based on environmental conditions</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an expert in farm labor management using AI."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Given the following environmental data, provide a dynamic labor schedule for planting, irrigation, and harvesting: <span class="hljs-subst">{environment_description}</span>"</span>}
    ]
)

labor_schedule = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(labor_schedule)
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725975552538/80a1bbed-94a3-4a13-8325-9ff184dfa44d.png" alt="80a1bbed-94a3-4a13-8325-9ff184dfa44d" class="image--center mx-auto" width="2048" height="1824" loading="lazy"></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Dynamic Farm Labor Schedule <span class="hljs-keyword">for</span> Today:**

- **Planting:** The weather forecast suggests light precipitation (<span class="hljs-number">20</span>mm), which <span class="hljs-keyword">is</span> suitable <span class="hljs-keyword">for</span> planting. Labor should focus on planting <span class="hljs-keyword">in</span> Zone A <span class="hljs-keyword">and</span> B during the morning hours when the temperature <span class="hljs-keyword">is</span> cooler (<span class="hljs-number">28</span>°C). Adjustments may be required <span class="hljs-keyword">if</span> precipitation increases.

- **Irrigation:** Soil moisture levels are at <span class="hljs-number">60</span>%, which <span class="hljs-keyword">is</span> adequate <span class="hljs-keyword">for</span> today. No immediate irrigation <span class="hljs-keyword">is</span> needed, but <span class="hljs-keyword">continue</span> to monitor moisture levels. If levels drop below <span class="hljs-number">50</span>%, schedule irrigation <span class="hljs-keyword">for</span> tomorrow morning before temperatures rise.

- **Harvesting:** There are no immediate harvesting requirements <span class="hljs-keyword">as</span> the crop <span class="hljs-keyword">is</span> <span class="hljs-keyword">in</span> the vegetative stage. However, labor should be allocated to check crop growth <span class="hljs-keyword">and</span> ensure pest control measures are <span class="hljs-keyword">in</span> place.

- **General Maintenance:** Given the weather conditions <span class="hljs-keyword">and</span> wind speed of <span class="hljs-number">10</span> km/h, it’s advisable to check equipment <span class="hljs-keyword">and</span> infrastructure stability. Allocate a small team to inspect irrigation systems <span class="hljs-keyword">and</span> prepare <span class="hljs-keyword">for</span> tomorrow<span class="hljs-string">'s forecasted heavier rain (50mm).</span>
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725975582528/b3bb2d60-928b-42b7-b3f6-3a9288ea8d18.png" alt="Dynamic Farm Labor Schedule for Today lists tasks under four headings: Planting, Irrigation, Harvesting, and General Maintenance. Planting suggests focusing on planting zones with lighter precipitation and cooler temperatures. Irrigation indicates soil moisture is adequate but to monitor it. Harvesting requires checking crop growth and pest control. General Maintenance advises inspecting equipment due to weather conditions and preparing for heavier rain tomorrow." class="image--center mx-auto" width="2048" height="1004" loading="lazy"></a></p>
<p>This example focused on <strong>enhancing farm labor management</strong> by dynamically generating a labor schedule for farming tasks (for example, planting, irrigation, harvesting) based on real-time environmental data such as weather, soil conditions, and crop growth stages. The LLM ensured that the labor schedule adapted to changing conditions.</p>
<h3 id="heading-precision-agriculture-for-labor-optimization"><strong>Precision Agriculture for Labor Optimization</strong></h3>
<p>Precision agriculture exemplifies the integration of AI and predictive analytics to optimize labor usage. This approach tailors farming practices to the specific needs of different field zones by analyzing real-time data on soil moisture levels, crop health, and weather conditions. Integrating AI into precision agriculture amplifies its effectiveness.</p>
<p>Imagine a farmer managing a vast field with varying soil types and fertility levels. Traditionally, uniform treatment would have been applied across the entire field, leading to inefficiencies and potential wastage of resources.</p>
<p>But AI can create detailed field maps, segmenting the land into manageable zones, each with tailored treatment plans. This ensures that labor-intensive tasks such as fertilization and pest control are precisely directed where needed, maximizing their impact and conserving resources.</p>
<p>AI's real-time data processing capabilities also enable predictive maintenance of equipment. By continuously monitoring machinery and identifying signs of wear or potential failure, AI-driven systems can schedule preemptive repairs, preventing costly downtime and labor disruptions. This predictive maintenance significantly enhances operational efficiency and prolongs the lifespan of equipment, leading to long-term cost savings.</p>
<p><strong>Now let’s see an example of how you could use precision agriculture with LLMs to optimize labor and resources:</strong></p>
<p><strong>Objective:</strong> Integrate an LLM to analyze real-time precision agriculture data and provide recommendations for labor allocation in specific zones based on soil moisture, crop health, and machine maintenance needs.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample precision agriculture data for a large field</span>
precision_ag_data = {
    <span class="hljs-string">"zones"</span>: {
        <span class="hljs-string">"Zone_1"</span>: {<span class="hljs-string">"soil_moisture"</span>: <span class="hljs-number">40</span>, <span class="hljs-string">"crop_health"</span>: <span class="hljs-string">"good"</span>, <span class="hljs-string">"fertilization_need"</span>: <span class="hljs-string">"low"</span>},
        <span class="hljs-string">"Zone_2"</span>: {<span class="hljs-string">"soil_moisture"</span>: <span class="hljs-number">30</span>, <span class="hljs-string">"crop_health"</span>: <span class="hljs-string">"moderate"</span>, <span class="hljs-string">"fertilization_need"</span>: <span class="hljs-string">"high"</span>},
        <span class="hljs-string">"Zone_3"</span>: {<span class="hljs-string">"soil_moisture"</span>: <span class="hljs-number">25</span>, <span class="hljs-string">"crop_health"</span>: <span class="hljs-string">"poor"</span>, <span class="hljs-string">"fertilization_need"</span>: <span class="hljs-string">"high"</span>}
    },
    <span class="hljs-string">"machinery_status"</span>: {
        <span class="hljs-string">"tractor_1"</span>: {<span class="hljs-string">"status"</span>: <span class="hljs-string">"operational"</span>, <span class="hljs-string">"maintenance_due_in_days"</span>: <span class="hljs-number">5</span>},
        <span class="hljs-string">"tractor_2"</span>: {<span class="hljs-string">"status"</span>: <span class="hljs-string">"requires_maintenance"</span>, <span class="hljs-string">"maintenance_due_in_days"</span>: <span class="hljs-number">0</span>}
    }
}

<span class="hljs-comment"># Convert precision agriculture data into a readable description</span>
agriculture_description = (
    <span class="hljs-string">f"Zone 1 has soil moisture at 40%, crop health is good, and low fertilization is needed. "</span>
    <span class="hljs-string">f"Zone 2 has soil moisture at 30%, crop health is moderate, and high fertilization is needed. "</span>
    <span class="hljs-string">f"Zone 3 has soil moisture at 25%, crop health is poor, and high fertilization is needed. "</span>
    <span class="hljs-string">f"Tractor 1 is operational and requires maintenance in 5 days. Tractor 2 requires immediate maintenance."</span>
)

<span class="hljs-comment"># Use LLM to generate labor allocation recommendations</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an AI expert specializing in precision agriculture labor optimization."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following precision agriculture data, provide labor recommendations for today: <span class="hljs-subst">{agriculture_description}</span>"</span>}
    ]
)

labor_recommendations = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(labor_recommendations)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725975637919/dac99545-e9b9-416e-8bb0-0b975c0b0fc5.png" alt="A screenshot of code written in Python. The code imports the 'openai' module and defines sample precision agriculture data for a large field, including zones with soil moisture, crop health, and fertilization needs, as well as the status of machinery. It then converts this data into a readable description and uses a language model (GPT-4) to generate labor allocation recommendations based on the provided data. The results are printed out at the end. - lunartech.ai" class="image--center mx-auto" width="2048" height="1750" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Labor Allocation Recommendations <span class="hljs-keyword">for</span> Today:**

- **Zone <span class="hljs-number">1</span>:** Since soil moisture <span class="hljs-keyword">is</span> at <span class="hljs-number">40</span>% <span class="hljs-keyword">and</span> crop health <span class="hljs-keyword">is</span> good, allocate minimal labor <span class="hljs-keyword">for</span> fertilization here. Focus on general crop monitoring, <span class="hljs-keyword">with</span> labor redirected to other zones.

- **Zone <span class="hljs-number">2</span>:** This zone requires more attention due to moderate crop health <span class="hljs-keyword">and</span> lower soil moisture (<span class="hljs-number">30</span>%). Allocate a team <span class="hljs-keyword">for</span> high-level fertilization tasks <span class="hljs-keyword">and</span> schedule irrigation <span class="hljs-keyword">in</span> the afternoon when temperatures are lower. Ensure laborers monitor soil moisture to avoid overwatering.

- **Zone <span class="hljs-number">3</span>:** Given the poor crop health <span class="hljs-keyword">and</span> low soil moisture (<span class="hljs-number">25</span>%), prioritize labor here. Allocate labor <span class="hljs-keyword">for</span> both high-level fertilization <span class="hljs-keyword">and</span> immediate irrigation. Additionally, plan a follow-up visit to assess crop recovery within <span class="hljs-number">48</span> hours. 

- **Machinery:** Tractor <span class="hljs-number">2</span> requires immediate maintenance <span class="hljs-keyword">and</span> should <span class="hljs-keyword">not</span> be used today. Tractor <span class="hljs-number">1</span> <span class="hljs-keyword">is</span> operational but will require maintenance <span class="hljs-keyword">in</span> the coming days. Assign a small maintenance crew to inspect Tractor <span class="hljs-number">1</span> <span class="hljs-keyword">and</span> prepare it <span class="hljs-keyword">for</span> upcoming tasks.

These labor recommendations will help optimize workforce distribution <span class="hljs-keyword">while</span> ensuring efficient resource use <span class="hljs-keyword">and</span> timely crop interventions.
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725975687418/2c2b192c-8bb9-4a40-8ffd-5d4001ae1c69.png" alt="Labor Allocation Recommendations for Today, detailing suggested labor tasks for three zones based on soil moisture and crop health, with additional notes on machinery maintenance. Zone 1 needs minimal labor, Zone 2 requires attention for high-level fertilization and irrigation, and Zone 3 prioritizes labor for fertilization and immediate irrigation. Tractor 2 needs maintenance, while Tractor 1 should be prepped for future tasks." class="image--center mx-auto" width="2048" height="1080" loading="lazy"></p>
<p>In this example, you saw how you can use <strong>precision agriculture</strong> with LLMs to analyze zone-specific data (soil moisture, crop health) and provide optimized labor allocation recommendations. It also considered machinery maintenance requirements to prevent downtime.</p>
<h3 id="heading-ai-driven-robotics-and-automation"><strong>AI-Driven Robotics and Automation</strong></h3>
<p>One of the most profound applications of AI in agriculture is in robotics and automation. AI-driven robots are designed to perform tasks traditionally requiring manual labor, such as planting, harvesting, and sorting. These robots are not only faster and more accurate but also capable of operating in conditions that might be challenging for human workers.</p>
<p>Take autonomous tractors, for instance. These vehicles use AI to navigate fields, planting seeds with pinpoint accuracy. They can work tirelessly, undeterred by fatigue or harsh weather, resulting in more consistent and higher-quality planting.</p>
<p>Similarly, harvesting robots equipped with advanced sensors and machine learning algorithms can distinguish between ripe and unripe fruits, ensuring optimal harvest times and reducing wastage.</p>
<p>Robotic process automation extends to post-harvest activities as well. Automated systems for sorting and packaging crops enhance the speed and accuracy of these labor-intensive tasks. These robots can be trained to recognize various crop qualities, ensuring only the best produce reaches the market.</p>
<p>AI-driven robotics can also adapt to various environmental conditions and crop varieties. This adaptability ensures that farms employing AI technologies enjoy consistent performance regardless of changes in soil types or weather patterns, overcoming one of the significant limitations of traditional farming methods.</p>
<h3 id="heading-sustainable-farming-practices"><strong>Sustainable Farming Practices</strong></h3>
<p>The integration of AI technologies in agriculture also paves the way for sustainable farming practices. By optimizing resource utilization and minimizing wastage, AI helps in reducing the environmental footprint of agricultural activities. For instance, precision irrigation systems using AI algorithms ensure water is used efficiently, addressing sustainability concerns in water-scarce regions.</p>
<p>Furthermore, AI can assist in monitoring and managing the health of crops with minimal chemical inputs. Machine learning algorithms can analyze data from sensors and detect signs of diseases or pest attacks early, allowing for targeted intervention with minimal pesticide use. This approach not only ensures healthier crops but also contributes to better environmental and consumer health.</p>
<p>Now you have a better idea about how AI can work to address the persistent issue of labor shortages in agriculture. By enhancing farm labor management, enabling precision agriculture, and driving robotics and automation, AI technologies significantly boost operational efficiency and productivity. These innovations ensure that farmers can manage their resources more effectively, maintain sustainable practices, and ultimately achieve higher crop yields.</p>
<h2 id="heading-chapter-4-predictive-analytics-and-machine-learning-in-crop-yield-improvement">Chapter 4: Predictive Analytics and Machine Learning in Crop Yield Improvement</h2>
<p>The advancements of AI in agriculture herald a transformative era where crop yields may potentially rise by as much as 70% by 2030. This leap hinges on the effective use of predictive analytics and machine learning, two potent tools that are dramatically reshaping the landscape of modern farming.</p>
<p>Let's delve deeply into how these technologies can elevate agricultural practices and drive substantial improvements in crop yield.</p>
<h3 id="heading-predictive-analytics-optimizing-agricultural-processes"><strong>Predictive Analytics: Optimizing Agricultural Processes</strong></h3>
<p>Predictive analytics leverages historical data, real-time information, and weather patterns to provide farmers with actionable insights. This highly nuanced approach facilitates precise decision-making, thus optimizing the entire agricultural value chain.</p>
<p>Imagine a farmer who has consistently struggled with unpredictable weather and its impact on planting schedules. By utilizing predictive analytics, historical weather patterns can be analyzed alongside real-time meteorological data to forecast the optimal planting period. This allows the farmer to sow crops under conditions most conducive to their growth, thus enhancing the probability of higher yields.</p>
<p>Predictive analytics also helps in fine-tuning irrigation strategies. Water scarcity is a persistent challenge in agriculture, particularly in arid regions. By analyzing soil moisture levels and weather forecasts, farmers can precisely schedule irrigation, ensuring plants receive the exact amount of water they need without wastage. This not only conserves water but also promotes healthier crop growth, which directly translates to improved yields.</p>
<p>Plant protection is another area where predictive analytics excels. By observing historical pest invasion data and current climatic conditions, farmers can predict pest outbreaks and implement timely, targeted interventions. Such foresight prevents extensive crop damage and reduces the dependency on chemical pesticides, fostering a more sustainable agricultural practice.</p>
<h3 id="heading-machine-learning-in-intelligent-decision-making"><strong>Machine Learning in Intelligent Decision-Making</strong></h3>
<p>Machine learning algorithms further elevate the capabilities of predictive analytics by enabling the creation of highly personalized AI models. These models are specifically tailored to a farm's unique characteristics—soil type, crop variety, local climate conditions—and can process vast datasets to offer precision farming recommendations.</p>
<p>Consider a scenario where a farm's soil is nutrient-deficient. Traditional methods might rely on broad-spectrum fertilizers, often leading to nutrient imbalance and soil degradation. But with machine learning, farmers can analyze soil samples to determine the specific nutrient deficiencies and develop custom fertilizer blends that address these gaps precisely. Over time, as the model ingests more data, its recommendations become more accurate, ensuring that crops receive optimal nutrition, which significantly boosts yields.</p>
<p>Machine learning can also revolutionize crop variety selection. Season after season, choosing the right crop variety to plant is a critical yet challenging decision. By analyzing data from past harvests, climate patterns, and market demands, machine learning models can predict which crop varieties are most likely to thrive and be profitable in a given region and season. This data-driven approach minimizes the guesswork and enhances the likelihood of successful harvests.</p>
<h3 id="heading-empowering-farmers-with-data-driven-insights"><strong>Empowering Farmers with Data-Driven Insights</strong></h3>
<p>The integration of predictive analytics and machine learning empowers farmers with real-time, data-driven insights, transforming agriculture into a precision-driven industry. Access to such precise information enables quick and informed decisions that maximize resources and mitigate risks.</p>
<p>Take, for example, the task of monitoring soil health. Traditionally, farmers relied on sporadic soil tests, which might miss critical variations in soil conditions. With continuous data collection through sensors and real-time analytics, farmers can monitor soil health consistently. If a sudden drop in soil moisture is detected, an immediate analysis can identify the cause, prompting timely corrective actions such as adjusted irrigation or the application of mulching to conserve moisture.</p>
<p>Weather predictions enhanced through machine learning algorithms also play a pivotal role. Real-time weather data can be continuously analyzed to detect emerging patterns or anomalies that might affect crop growth. For instance, an impending storm that could potentially cause flooding can be predicted, allowing farmers to apply preemptive measures such as improving drainage systems or temporarily covering crops to protect them.</p>
<p>Moreover, management practices can be adjusted dynamically based on insights from data on plant health. Advanced sensors can monitor plant conditions, identifying early signs of disease or nutrient deficiency. With immediate feedback, farmers can apply the necessary treatments long before visible symptoms appear, thus saving crops and increasing yields.</p>
<h3 id="heading-advanced-insights-for-sustainable-farming"><strong>Advanced Insights for Sustainable Farming</strong></h3>
<p>Beyond immediate yield improvements, predictive analytics and machine learning promote sustainable farming practices by optimizing resource use and minimizing environmental impact.</p>
<p>Precision in fertilizer application, as discussed earlier, prevents over-fertilization and reduces the risk of groundwater contamination. Similarly, efficient water use strategies ensure that valuable freshwater resources are conserved, which is especially crucial in regions facing water scarcity.</p>
<p>By promoting sustainable practices, these technologies help build resilient agricultural systems capable of withstanding the adverse effects of climate change. For example, predictive models that anticipate climate variability and its impact on crop cycles enable farmers to adapt their strategies proactively. This adaptive capacity is vital for maintaining productivity as weather patterns become increasingly unpredictable.</p>
<h3 id="heading-concrete-examples-of-success"><strong>Concrete Examples of Success</strong></h3>
<p>Real-world applications of these technologies offer compelling evidence of their efficacy. In the United States, the USDA has been leveraging predictive analytics to forecast corn yield with remarkable accuracy. By integrating satellite imagery, weather data, and advanced analytics, the USDA can predict yield variations and guide farmers in optimizing their practices accordingly.</p>
<p>In India, machine learning models have been employed to improve rice yields. By analyzing soil health, weather patterns, and pest data, these models provide tailored advice to farmers, resulting in significant yield increases. The model's success in one of the most challenging agricultural environments underscores the transformative potential of AI-driven solutions in diverse settings.</p>
<h4 id="heading-code-examples">Code Examples</h4>
<p>Here are two examples that demonstrate how LLM (Large Language Models) applications can be integrated into the predictive analytics and machine learning aspects of agriculture to enhance crop yield optimization and sustainable farming practices.</p>
<h4 id="heading-example-1-predictive-analytics-for-optimizing-agricultural-processes"><strong>Example 1: Predictive analytics for optimizing agricultural processes</strong></h4>
<p><strong>Objective:</strong> Utilize an LLM to generate insights for a farmer on the optimal planting, irrigation, and pest control schedules based on historical weather patterns, real-time meteorological data, and soil moisture levels.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

<span class="hljs-comment"># Sample data on historical and current weather, soil moisture, and pest data</span>
agricultural_data = {
    <span class="hljs-string">"historical_weather"</span>: <span class="hljs-string">"Over the past 10 years, this region has experienced optimal planting conditions between March 15 and April 10, with a dry spell in mid-April."</span>,
    <span class="hljs-string">"current_weather"</span>: {
        <span class="hljs-string">"today"</span>: {<span class="hljs-string">"temperature"</span>: <span class="hljs-number">25</span>, <span class="hljs-string">"humidity"</span>: <span class="hljs-number">60</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">0</span>, <span class="hljs-string">"wind_speed"</span>: <span class="hljs-number">10</span>},
        <span class="hljs-string">"forecast"</span>: [
            {<span class="hljs-string">"date"</span>: <span class="hljs-string">"2024-03-18"</span>, <span class="hljs-string">"temperature"</span>: <span class="hljs-number">22</span>, <span class="hljs-string">"humidity"</span>: <span class="hljs-number">55</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">5</span>},
            {<span class="hljs-string">"date"</span>: <span class="hljs-string">"2024-03-19"</span>, <span class="hljs-string">"temperature"</span>: <span class="hljs-number">24</span>, <span class="hljs-string">"humidity"</span>: <span class="hljs-number">50</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">0</span>}
        ]
    },
    <span class="hljs-string">"soil_moisture"</span>: <span class="hljs-number">35</span>,  <span class="hljs-comment"># percentage</span>
    <span class="hljs-string">"pest_risk"</span>: <span class="hljs-string">"Based on historical pest data and current climate conditions, there is a high risk of pest outbreaks in late April."</span>
}

<span class="hljs-comment"># Create a readable summary of the data for the LLM</span>
data_summary = (
    <span class="hljs-string">f"Historical weather data: <span class="hljs-subst">{agricultural_data[<span class="hljs-string">'historical_weather'</span>]}</span>. "</span>
    <span class="hljs-string">f"Today's weather: Temperature <span class="hljs-subst">{agricultural_data[<span class="hljs-string">'current_weather'</span>][<span class="hljs-string">'today'</span>][<span class="hljs-string">'temperature'</span>]}</span>°C, "</span>
    <span class="hljs-string">f"Humidity <span class="hljs-subst">{agricultural_data[<span class="hljs-string">'current_weather'</span>][<span class="hljs-string">'today'</span>][<span class="hljs-string">'humidity'</span>]}</span>%, "</span>
    <span class="hljs-string">f"Precipitation <span class="hljs-subst">{agricultural_data[<span class="hljs-string">'current_weather'</span>][<span class="hljs-string">'today'</span>][<span class="hljs-string">'precipitation'</span>]}</span>mm, "</span>
    <span class="hljs-string">f"and Wind Speed <span class="hljs-subst">{agricultural_data[<span class="hljs-string">'current_weather'</span>][<span class="hljs-string">'today'</span>][<span class="hljs-string">'wind_speed'</span>]}</span> km/h. "</span>
    <span class="hljs-string">f"Soil moisture is currently <span class="hljs-subst">{agricultural_data[<span class="hljs-string">'soil_moisture'</span>]}</span>%. "</span>
    <span class="hljs-string">f"Pest risk: <span class="hljs-subst">{agricultural_data[<span class="hljs-string">'pest_risk'</span>]}</span>."</span>
)

<span class="hljs-comment"># Use an LLM to generate actionable insights for the farmer based on this data</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an expert in agriculture with a focus on predictive analytics."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following data, suggest optimal planting, irrigation, and pest control strategies: <span class="hljs-subst">{data_summary}</span>"</span>}
    ]
)

recommendations = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(recommendations)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725975915504/36d15010-d9ed-49fa-9dce-19d08dafb8ef.png" alt="A screenshot of Python code is shown. The code imports the OpenAI and datetime libraries and defines a sample dataset on historical and current weather, soil moisture, and pest data. It includes keys for historical weather, current weather, soil moisture, and pest risk, with values representing various data points. The code then creates a readable summary of this data for a language model and uses the OpenAI API to generate actionable insights for farmers based on the data provided. The result is printed at the end." class="image--center mx-auto" width="2048" height="1972" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Optimal Planting Strategy:**
Based on historical data, the ideal planting window <span class="hljs-keyword">is</span> between March <span class="hljs-number">15</span> <span class="hljs-keyword">and</span> April <span class="hljs-number">10.</span> Given the current weather forecast <span class="hljs-keyword">and</span> soil moisture level of <span class="hljs-number">35</span>%, it <span class="hljs-keyword">is</span> advisable to begin planting on March <span class="hljs-number">19</span>, when temperatures will be around <span class="hljs-number">24</span>°C <span class="hljs-keyword">and</span> precipitation <span class="hljs-keyword">is</span> expected to be minimal.

**Irrigation Strategy:**
With soil moisture at <span class="hljs-number">35</span>%, irrigation <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> urgently required today. However, monitor moisture levels closely over the next week, especially after March <span class="hljs-number">19.</span> If the soil moisture drops below <span class="hljs-number">30</span>%, consider scheduling irrigation <span class="hljs-keyword">in</span> the early morning <span class="hljs-keyword">or</span> late evening to reduce evaporation.

**Pest Control Strategy:**
There <span class="hljs-keyword">is</span> a high risk of pest outbreaks <span class="hljs-keyword">in</span> late April. It <span class="hljs-keyword">is</span> recommended to implement preventative measures, such <span class="hljs-keyword">as</span> applying organic pest deterrents, during the second week of April. Regular monitoring of pest activity during this period <span class="hljs-keyword">is</span> crucial to prevent damage to crops.
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725975998098/83536fd7-8789-4087-bafa-193f06d9b12d.png" alt="A terminal window displaying three agriculture strategies: optimal planting, irrigation, and pest control. The optimal planting strategy suggests planting between March 15 and April 10, with a recommended date of March 19. The irrigation strategy advises monitoring soil moisture, currently at 35%, and irrigating if it drops below 30%. The pest control strategy warns of a high risk of pest outbreaks in late April and recommends applying organic pest deterrents during the second week of April." class="image--center mx-auto" width="2048" height="894" loading="lazy"></a></p>
<h4 id="heading-example-2-machine-learning-for-intelligent-decision-making-in-agriculture"><strong>Example 2: Machine Learning for intelligent decision-making in agriculture</strong></h4>
<p><strong>Objective:</strong> Use an LLM to generate recommendations for custom fertilizer blends and optimal crop variety selection based on machine learning models that analyze soil type, nutrient levels, and local climate data.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample soil and climate data for a farm</span>
farm_data = {
    <span class="hljs-string">"soil_type"</span>: <span class="hljs-string">"clay"</span>,
    <span class="hljs-string">"soil_nutrients"</span>: {<span class="hljs-string">"nitrogen"</span>: <span class="hljs-number">30</span>, <span class="hljs-string">"phosphorus"</span>: <span class="hljs-number">15</span>, <span class="hljs-string">"potassium"</span>: <span class="hljs-number">40</span>},  <span class="hljs-comment"># ppm</span>
    <span class="hljs-string">"climate_conditions"</span>: {<span class="hljs-string">"average_temperature"</span>: <span class="hljs-number">28</span>, <span class="hljs-string">"rainfall"</span>: <span class="hljs-string">"moderate"</span>, <span class="hljs-string">"humidity"</span>: <span class="hljs-number">65</span>},
    <span class="hljs-string">"historical_crop_yield"</span>: {
        <span class="hljs-string">"wheat"</span>: {<span class="hljs-string">"yield_per_hectare"</span>: <span class="hljs-number">3000</span>},
        <span class="hljs-string">"corn"</span>: {<span class="hljs-string">"yield_per_hectare"</span>: <span class="hljs-number">2800</span>},
        <span class="hljs-string">"rice"</span>: {<span class="hljs-string">"yield_per_hectare"</span>: <span class="hljs-number">4000</span>}
    }
}

<span class="hljs-comment"># Convert farm data to a readable description</span>
farm_description = (
    <span class="hljs-string">f"The farm's soil is clay-based, with nutrient levels of nitrogen at <span class="hljs-subst">{farm_data[<span class="hljs-string">'soil_nutrients'</span>][<span class="hljs-string">'nitrogen'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"phosphorus at <span class="hljs-subst">{farm_data[<span class="hljs-string">'soil_nutrients'</span>][<span class="hljs-string">'phosphorus'</span>]}</span> ppm, and potassium at <span class="hljs-subst">{farm_data[<span class="hljs-string">'soil_nutrients'</span>][<span class="hljs-string">'potassium'</span>]}</span> ppm. "</span>
    <span class="hljs-string">f"Climate conditions include an average temperature of <span class="hljs-subst">{farm_data[<span class="hljs-string">'climate_conditions'</span>][<span class="hljs-string">'average_temperature'</span>]}</span>°C, "</span>
    <span class="hljs-string">f"moderate rainfall, and humidity at <span class="hljs-subst">{farm_data[<span class="hljs-string">'climate_conditions'</span>][<span class="hljs-string">'humidity'</span>]}</span>%. "</span>
    <span class="hljs-string">f"Historical yields for wheat, corn, and rice have been 3000, 2800, and 4000 kilograms per hectare, respectively."</span>
)

<span class="hljs-comment"># Use an LLM to suggest custom fertilizer blends and optimal crop variety based on this data</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an agricultural expert with a focus on machine learning and crop yield optimization."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following farm data, suggest a custom fertilizer blend and optimal crop variety for the upcoming season: <span class="hljs-subst">{farm_description}</span>"</span>}
    ]
)

crop_and_fertilizer_recommendations = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(crop_and_fertilizer_recommendations)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725976048069/a7930c97-c8a1-40e9-b316-97786b5321fa.png" alt="A screenshot of Python code using the OpenAI API to suggest optimal crop varieties and custom fertilizer blends based on sample soil and climate data for a farm. The dataset includes soil type, nutrient levels, climate conditions, and historical crop yield. The code converts this data into a readable description and sends it to the OpenAI model for recommendations." class="image--center mx-auto" width="2048" height="1860" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Custom Fertilizer Blend Recommendation:**
Given the nutrient levels <span class="hljs-keyword">in</span> your clay soil (<span class="hljs-number">30</span> ppm nitrogen, <span class="hljs-number">15</span> ppm phosphorus, <span class="hljs-number">40</span> ppm potassium), it <span class="hljs-keyword">is</span> recommended to apply a balanced fertilizer <span class="hljs-keyword">with</span> the following ratio:
- Nitrogen: <span class="hljs-number">40</span>%
- Phosphorus: <span class="hljs-number">25</span>%
- Potassium: <span class="hljs-number">35</span>%

You can achieve this blend by combining urea (<span class="hljs-keyword">for</span> nitrogen), triple superphosphate (<span class="hljs-keyword">for</span> phosphorus), <span class="hljs-keyword">and</span> potassium sulfate. Apply the fertilizer before the planting season <span class="hljs-keyword">and</span> follow up <span class="hljs-keyword">with</span> additional nitrogen during the growth phase, especially <span class="hljs-keyword">for</span> nitrogen-hungry crops like wheat.

**Optimal Crop Variety Recommendation:**
Based on the climate conditions (<span class="hljs-number">28</span>°C average temperature, moderate rainfall, <span class="hljs-keyword">and</span> <span class="hljs-number">65</span>% humidity), the optimal crop variety <span class="hljs-keyword">for</span> your farm would be rice. Rice has historically produced the highest <span class="hljs-keyword">yield</span> on your farm (<span class="hljs-number">4000</span> kg/hectare) <span class="hljs-keyword">and</span> performs well <span class="hljs-keyword">in</span> clay soil <span class="hljs-keyword">with</span> moderate water availability. Choose a high-<span class="hljs-keyword">yield</span>, drought-resistant rice variety <span class="hljs-keyword">for</span> this season to maximize output <span class="hljs-keyword">while</span> minimizing water usage.

Wheat <span class="hljs-keyword">is</span> also a viable option, but <span class="hljs-keyword">with</span> lower <span class="hljs-keyword">yield</span> potential. However, <span class="hljs-keyword">if</span> market demand <span class="hljs-keyword">is</span> higher <span class="hljs-keyword">for</span> wheat, consider alternating crops <span class="hljs-keyword">or</span> employing crop rotation to maintain soil health.
</code></pre>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725976110962/bab86c00-54a7-482e-844a-8b7e473e91d3.png" alt="bab86c00-54a7-482e-844a-8b7e473e91d3" class="image--center mx-auto" width="2048" height="1116" loading="lazy"></p>
<p><strong>Example 1</strong> demonstrates the use of <strong>predictive analytics</strong> with an LLM to provide actionable recommendations for optimal planting, irrigation, and pest control schedules based on historical weather patterns, real-time data, and soil conditions.</p>
<p><strong>Example 2</strong> showcases <strong>machine learning</strong> applied to agriculture, where an LLM generates custom fertilizer recommendations and suggests the optimal crop variety based on farm-specific data such as soil nutrients, climate conditions, and historical crop yield performance.</p>
<p>In both examples, LLMs act as a powerful interface between the data and the farmer, providing tailored insights to optimize decision-making and enhance crop yields.</p>
<p>As you can see, the integration of predictive analytics and machine learning in agriculture is a technological advancement that represents a paradigm shift towards a future where farming is driven by precision, sustainability, and unprecedented productivity. By harnessing historical data and real-time information, farmers can optimize every aspect of crop management, from planting to harvest, ensuring higher yields and promoting environmental stewardship.</p>
<p>For farmers, researchers, and policymakers alike, the challenge is to embrace these tools, continually innovate, and drive the agricultural sector towards a future of smart, sustainable, and highly productive farming practices.</p>
<h2 id="heading-chapter-5-how-to-leverage-big-data-and-computer-vision-in-farming">Chapter 5: How to Leverage Big Data and Computer Vision in Farming</h2>
<p>As we explore how AI can help improve agricultural practices, we need to explore the nuances of how big data and computer vision technologies play crucial roles in achieving such ambitious goals.</p>
<p>This chapter will give you a comprehensive overview of the transformative impact that these technologies have on modern agriculture, offering detailed insights and practical examples that highlight their significance and implementation.</p>
<h3 id="heading-the-role-of-big-data-in-precision-agriculture"><strong>The Role of Big Data in Precision Agriculture</strong></h3>
<p>Big data analytics is a cornerstone of precision agriculture, where the primary aim is to monitor and manage field variability more effectively.</p>
<p>Farmers collect vast amounts of data through sensors, drones, and satellite imagery, encompassing soil conditions, weather patterns, and crop health. This data is then analyzed to elucidate trends and patterns that inform decision-making.</p>
<p>For instance, understanding soil moisture levels can help optimize irrigation schedules, while tracking weather conditions enables better planning for planting and harvesting.</p>
<p>The predictive power of big data can also guide the application of fertilizers and pesticides, ensuring they are used only when necessary and in precisely the right amounts. This not only saves costs but also minimizes the environmental impact of agricultural practices, addressing the pressing issues of sustainability and resource conservation.</p>
<h3 id="heading-enhancing-crop-monitoring-with-computer-vision"><strong>Enhancing Crop Monitoring with Computer Vision</strong></h3>
<p>Computer vision technologies significantly enhance crop monitoring by providing high-resolution, real-time images of fields. Drones equipped with multispectral and hyperspectral cameras can fly over large areas, capturing detailed images that reveal information invisible to the naked eye—a critical advantage for early detection of stress factors such as pests, diseases, and nutrient deficiencies.</p>
<p>For instance, a farmer can use drone imagery to identify sections of a field suffering from water stress. By pinpointing these areas precisely, irrigation can be targeted and regulated accordingly, avoiding over-watering or under-watering, which can detrimentally affect crop yield.</p>
<p>Similarly, early detection of pest infestation through computer vision allows for timely intervention, mitigating damage and potential yield loss.</p>
<h3 id="heading-ai-models-for-predicting-crop-yields"><strong>AI Models for Predicting Crop Yields</strong></h3>
<p>AI-powered predictive analytics are revolutionizing the way farmers forecast crop yields. By integrating various data sources, including current and historical soil quality data, weather patterns, and crop health metrics, AI models generate accurate yield predictions. These models use machine learning algorithms to continuously improve their accuracy as they are exposed to more data.</p>
<p>For example, if historical data indicates that a particular crop yield decreases under specific weather conditions, the AI model can predict similar outcomes and recommend proactive measures. This might include adjusting planting dates, choosing drought-resistant crop varieties, or optimizing irrigation schedules.</p>
<p>Such insights empower farmers to make informed decisions that enhance productivity and reduce risks associated with unforeseen variables.</p>
<h3 id="heading-empowering-farm-management-with-data-driven-insights"><strong>Empowering Farm Management with Data-Driven Insights</strong></h3>
<p>Farm management software integrated with big data analytics and AI provides a holistic view of farm operations. These platforms consolidate data on everything from soil moisture levels to fertilizer usage, making it easier for farmers to plan and execute their activities efficiently. By offering real-time insights and recommendations, these tools help in optimizing resource allocation, thus enhancing productivity and sustainability.</p>
<p>Consider a scenario where a farmer uses farm management software to track the efficiency of different watering systems. The software can analyze data from various sections of the farm, revealing which system operates most efficiently under different conditions. This allows the farmer to make data-driven decisions on where to invest in irrigation infrastructure, thereby improving water use efficiency and reducing costs.</p>
<h3 id="heading-sustainable-farming-practices-through-data-integration"><strong>Sustainable Farming Practices Through Data Integration</strong></h3>
<p>Integrating data from multiple sources not only optimizes individual farming practices but also promotes overall sustainability. By combining data on soil health, weather patterns, and crop performance, farmers can adopt practices that improve soil fertility, reduce chemical inputs, and conserve water. For instance, data-driven crop rotation schedules can enhance soil health and reduce pest and disease pressure, consequently lowering reliance on synthetic fertilizers and pesticides.</p>
<p>Additionally, big data and computer vision can support the adoption of precision irrigation and fertigation techniques. For example, data on soil moisture levels and plant growth stages can be used to apply water and nutrients precisely when and where they are needed, reducing waste and environmental impact. This aligns with broader goals of sustainability and resource conservation, ensuring that agricultural practices remain viable and productive in the face of climate change and a growing global population.</p>
<h4 id="heading-code-examples-1">Code Examples</h4>
<p>Below are three examples that demonstrate how LLM applications can be integrated into AI-enhanced farming to increase crop yields by up to 70% by 2030. These examples showcase how LLMs can be used to analyze big data, interpret computer vision inputs, and generate predictive analytics for decision-making.</p>
<h4 id="heading-example-1-big-data-in-precision-agriculture-for-irrigation-and-fertilization"><strong>Example 1: Big data in precision agriculture for irrigation and fertilization</strong></h4>
<p><strong>Objective:</strong> Use an LLM to analyze data from sensors, satellite imagery, and weather forecasts. Based on the analysis, the LLM generates an optimal irrigation and fertilization schedule.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample big data inputs: weather forecasts, soil sensors, and satellite imagery</span>
big_data = {
    <span class="hljs-string">"weather_forecast"</span>: {
        <span class="hljs-string">"today"</span>: {<span class="hljs-string">"temp"</span>: <span class="hljs-number">28</span>, <span class="hljs-string">"humidity"</span>: <span class="hljs-number">50</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">10</span>},
        <span class="hljs-string">"next_week"</span>: [
            {<span class="hljs-string">"day"</span>: <span class="hljs-string">"Monday"</span>, <span class="hljs-string">"temp"</span>: <span class="hljs-number">30</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">5</span>},
            {<span class="hljs-string">"day"</span>: <span class="hljs-string">"Tuesday"</span>, <span class="hljs-string">"temp"</span>: <span class="hljs-number">32</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">0</span>}
        ]
    },
    <span class="hljs-string">"soil_conditions"</span>: {
        <span class="hljs-string">"moisture_level"</span>: <span class="hljs-number">35</span>,  <span class="hljs-comment"># in percentage</span>
        <span class="hljs-string">"nutrient_levels"</span>: {<span class="hljs-string">"nitrogen"</span>: <span class="hljs-number">40</span>, <span class="hljs-string">"phosphorus"</span>: <span class="hljs-number">20</span>, <span class="hljs-string">"potassium"</span>: <span class="hljs-number">30</span>}  <span class="hljs-comment"># ppm</span>
    },
    <span class="hljs-string">"satellite_imagery"</span>: {
        <span class="hljs-string">"crop_health_index"</span>: <span class="hljs-number">0.8</span>,  <span class="hljs-comment"># normalized index (0 to 1)</span>
        <span class="hljs-string">"vegetation_density"</span>: <span class="hljs-string">"moderate"</span>
    }
}

<span class="hljs-comment"># Generate a description for the LLM</span>
big_data_description = (
    <span class="hljs-string">f"The weather forecast indicates a temperature of <span class="hljs-subst">{big_data[<span class="hljs-string">'weather_forecast'</span>][<span class="hljs-string">'today'</span>][<span class="hljs-string">'temp'</span>]}</span>°C "</span>
    <span class="hljs-string">f"with 50% humidity and 10mm of precipitation today. Soil moisture is at <span class="hljs-subst">{big_data[<span class="hljs-string">'soil_conditions'</span>][<span class="hljs-string">'moisture_level'</span>]}</span>%. "</span>
    <span class="hljs-string">f"Nutrient levels are: nitrogen at <span class="hljs-subst">{big_data[<span class="hljs-string">'soil_conditions'</span>][<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'nitrogen'</span>]}</span> ppm, phosphorus at "</span>
    <span class="hljs-string">f"<span class="hljs-subst">{big_data[<span class="hljs-string">'soil_conditions'</span>][<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'phosphorus'</span>]}</span> ppm, and potassium at <span class="hljs-subst">{big_data[<span class="hljs-string">'soil_conditions'</span>][<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'potassium'</span>]}</span> ppm. "</span>
    <span class="hljs-string">f"The crop health index from satellite imagery is 0.8, indicating moderate vegetation density."</span>
)

<span class="hljs-comment"># Use LLM to generate optimal irrigation and fertilization recommendations</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an AI agricultural assistant specializing in big data analysis for irrigation and fertilization."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following big data, provide irrigation and fertilization recommendations: <span class="hljs-subst">{big_data_description}</span>"</span>}
    ]
)

recommendations = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(recommendations)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725976543591/4284c77b-f0bb-41b3-b41e-ea02c08355d8.png" alt="Code snippet displaying the use of OpenAI's GPT-4 to generate agricultural insights based on weather forecasts, soil conditions, and satellite imagery. The script includes defining big data inputs, generating a description for the language model, and creating irrigation and fertilization recommendations based on the data. - lunartech.ai" class="image--center mx-auto" width="2048" height="2122" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Irrigation Recommendations:**
Given the current soil moisture level of <span class="hljs-number">35</span>%, <span class="hljs-keyword">and</span> the precipitation forecast of <span class="hljs-number">10</span>mm today, additional irrigation <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> required today. However, <span class="hljs-keyword">as</span> the temperature rises to <span class="hljs-number">30</span><span class="hljs-number">-32</span>°C next week, plan <span class="hljs-keyword">for</span> irrigation on Tuesday, especially <span class="hljs-keyword">if</span> soil moisture drops below <span class="hljs-number">30</span>%.

**Fertilization Recommendations:**
- Nitrogen levels are at <span class="hljs-number">40</span> ppm, which <span class="hljs-keyword">is</span> slightly below the optimal range <span class="hljs-keyword">for</span> active growth phases. Apply nitrogen-rich fertilizer at <span class="hljs-number">25</span>% of the recommended dose over the next two days.
- Phosphorus levels are low at <span class="hljs-number">20</span> ppm. Apply phosphorus-rich fertilizer at <span class="hljs-number">50</span>% of the standard rate to improve root development.
- Potassium levels are adequate but can be boosted <span class="hljs-keyword">with</span> a light application to support flowering <span class="hljs-keyword">and</span> fruiting.
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725976591868/867445a1-caea-4a3b-917a-70f82cd2f81d.png" alt="A black terminal screen displays text with irrigation and fertilization recommendations. The text highlights soil moisture at 35%, no additional irrigation needed today, potential irrigation next Tuesday if soil moisture drops below 30%, nitrogen levels at 40 ppm needing 25% fertilizer dose, phosphorus at 20 ppm needing 50% fertilizer dose, and adequate potassium levels needing light application for flowering and fruiting. - lunartech.ai" class="image--center mx-auto" width="2048" height="818" loading="lazy"></a></p>
<h4 id="heading-example-2-computer-vision-for-detecting-crop-diseases-and-nutrient-deficiencies"><strong>Example 2: Computer vision for detecting crop diseases and nutrient deficiencies</strong></h4>
<p><strong>Objective:</strong> Integrate computer vision data from drones into an LLM to analyze crop health and generate early disease detection and nutrient deficiency recommendations.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample data from drone-based computer vision system</span>
vision_data = {
    <span class="hljs-string">"field_images"</span>: {
        <span class="hljs-string">"zones"</span>: {
            <span class="hljs-string">"Zone_1"</span>: {<span class="hljs-string">"water_stress"</span>: <span class="hljs-string">"none"</span>, <span class="hljs-string">"nutrient_deficiency"</span>: <span class="hljs-string">"low nitrogen"</span>, <span class="hljs-string">"disease_spots"</span>: <span class="hljs-string">"none"</span>},
            <span class="hljs-string">"Zone_2"</span>: {<span class="hljs-string">"water_stress"</span>: <span class="hljs-string">"moderate"</span>, <span class="hljs-string">"nutrient_deficiency"</span>: <span class="hljs-string">"none"</span>, <span class="hljs-string">"disease_spots"</span>: <span class="hljs-string">"possible fungal infection"</span>}
        }
    },
    <span class="hljs-string">"crop_health_metrics"</span>: {
        <span class="hljs-string">"average_growth_rate"</span>: <span class="hljs-string">"good"</span>,
        <span class="hljs-string">"vegetation_health_index"</span>: <span class="hljs-number">0.85</span>,  <span class="hljs-comment"># 0 to 1 scale</span>
        <span class="hljs-string">"detected_pests"</span>: <span class="hljs-string">"none"</span>
    }
}

<span class="hljs-comment"># Generate a description for the LLM based on vision data</span>
vision_data_description = (
    <span class="hljs-string">f"Zone 1 has no water stress, but low nitrogen deficiency is detected, with no disease spots. "</span>
    <span class="hljs-string">f"Zone 2 has moderate water stress, no nutrient deficiencies, but possible fungal infection spots were detected. "</span>
    <span class="hljs-string">f"Average growth rate is good, with a vegetation health index of 0.85, and no pests detected."</span>
)

<span class="hljs-comment"># Use LLM to generate recommendations based on computer vision analysis</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an expert in agricultural disease management and nutrient analysis."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following computer vision data, provide recommendations for nutrient deficiency and disease management: <span class="hljs-subst">{vision_data_description}</span>"</span>}
    ]
)

crop_health_recommendations = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(crop_health_recommendations)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725976646011/26fa3bd2-3799-48a4-ac79-592f2b2d09d9.png" alt="A screenshot of a Python script for analyzing drone-based computer vision data related to agricultural health metrics. The script includes code for defining the vision data, generating a description based on the data, and using a language model (GPT-4) to generate recommendations for nutrient deficiency and disease management." class="image--center mx-auto" width="2048" height="1860" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Zone <span class="hljs-number">1</span> Recommendations:**
- Address the low nitrogen deficiency by applying nitrogen-rich fertilizer, such <span class="hljs-keyword">as</span> urea, at a rate of <span class="hljs-number">30</span>% of the recommended dose. Monitor crop growth over the next week <span class="hljs-keyword">for</span> improvement.

**Zone <span class="hljs-number">2</span> Recommendations:**
- The moderate water stress should be alleviated by implementing targeted irrigation immediately. Focus on ensuring consistent soil moisture levels to reduce plant stress.
- The possible fungal infection should be treated <span class="hljs-keyword">with</span> an appropriate fungicide. Apply a broad-spectrum fungicide <span class="hljs-keyword">as</span> a preventative measure, <span class="hljs-keyword">and</span> closely monitor the affected areas <span class="hljs-keyword">for</span> further spread.
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725976687010/4abd8715-98be-445a-9e23-98292911ad0f.png" alt="The image shows a text document with agricultural recommendations. Zone 1 suggests addressing low nitrogen deficiency by applying nitrogen-rich fertilizer at 30% of the recommended dose and monitoring crop growth. Zone 2 recommends alleviating water stress through targeted irrigation, maintaining consistent soil moisture, and treating a possible fungal infection with a broad-spectrum fungicide while monitoring affected areas. - lunartech.ai" class="image--center mx-auto" width="2048" height="706" loading="lazy"></a></p>
<h4 id="heading-example-3-predictive-analytics-for-crop-yield-forecasting"><strong>Example 3: Predictive analytics for crop yield forecasting</strong></h4>
<p><strong>Objective:</strong> Use LLMs to process historical data and predictive models to estimate crop yields based on real-time weather patterns and soil conditions.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample historical and real-time data for predictive analytics</span>
historical_data = {
    <span class="hljs-string">"crop_type"</span>: <span class="hljs-string">"corn"</span>,
    <span class="hljs-string">"historical_yield_per_hectare"</span>: <span class="hljs-number">5000</span>,  <span class="hljs-comment"># kg/ha</span>
    <span class="hljs-string">"historical_weather_patterns"</span>: {
        <span class="hljs-string">"optimal_temp_range"</span>: [<span class="hljs-number">25</span>, <span class="hljs-number">30</span>],  <span class="hljs-comment"># °C</span>
        <span class="hljs-string">"optimal_precipitation"</span>: <span class="hljs-number">100</span>  <span class="hljs-comment"># mm/month</span>
    }
}

real_time_data = {
    <span class="hljs-string">"current_temp"</span>: <span class="hljs-number">28</span>,  <span class="hljs-comment"># °C</span>
    <span class="hljs-string">"current_precipitation"</span>: <span class="hljs-number">90</span>,  <span class="hljs-comment"># mm this month</span>
    <span class="hljs-string">"soil_moisture"</span>: <span class="hljs-number">50</span>  <span class="hljs-comment"># percentage</span>
}

<span class="hljs-comment"># Generate a description of the data for the LLM</span>
data_description = (
    <span class="hljs-string">f"The crop is corn, with a historical average yield of 5000 kg/hectare. The optimal temperature range for growth is between "</span>
    <span class="hljs-string">f"<span class="hljs-subst">{historical_data[<span class="hljs-string">'historical_weather_patterns'</span>][<span class="hljs-string">'optimal_temp_range'</span>][<span class="hljs-number">0</span>]}</span>°C and "</span>
    <span class="hljs-string">f"<span class="hljs-subst">{historical_data[<span class="hljs-string">'historical_weather_patterns'</span>][<span class="hljs-string">'optimal_temp_range'</span>][<span class="hljs-number">1</span>]}</span>°C, and optimal precipitation is 100 mm per month. "</span>
    <span class="hljs-string">f"Current conditions show a temperature of <span class="hljs-subst">{real_time_data[<span class="hljs-string">'current_temp'</span>]}</span>°C, precipitation of <span class="hljs-subst">{real_time_data[<span class="hljs-string">'current_precipitation'</span>]}</span> mm, "</span>
    <span class="hljs-string">f"and soil moisture at <span class="hljs-subst">{real_time_data[<span class="hljs-string">'soil_moisture'</span>]}</span>%."</span>
)

<span class="hljs-comment"># Use LLM to generate a crop yield forecast based on this data</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an expert in crop yield forecasting using predictive analytics."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following data, provide an estimated crop yield and suggestions for improving yield potential: <span class="hljs-subst">{data_description}</span>"</span>}
    ]
)

yield_forecast = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(yield_forecast)
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725976755405/7fc5b658-7a88-4719-91c9-94cee8ef6a4d.png" alt="A code snippet written in Python that uses the OpenAI API to generate crop yield forecasts based on historical and real-time data. The code includes sample historical data for corn, real-time weather data, and a description generator for input to the model. The final section calls the OpenAI ChatCompletion.create function, passing the description and retrieving the yield forecast. - lunartech.ai" class="image--center mx-auto" width="2048" height="1972" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Crop Yield Forecast:**
Given the current temperature of <span class="hljs-number">28</span>°C, which falls within the optimal range <span class="hljs-keyword">for</span> corn growth (<span class="hljs-number">25</span><span class="hljs-number">-30</span>°C), <span class="hljs-keyword">and</span> a slightly lower-than-optimal precipitation level of <span class="hljs-number">90</span> mm (optimal <span class="hljs-keyword">is</span> <span class="hljs-number">100</span> mm), the crop <span class="hljs-keyword">yield</span> <span class="hljs-keyword">is</span> projected to be around <span class="hljs-number">4800</span> kg/hectare. The current soil moisture level of <span class="hljs-number">50</span>% supports healthy growth.

**Suggestions <span class="hljs-keyword">for</span> Improving Yield:**
- To maximize <span class="hljs-keyword">yield</span> potential, consider increasing irrigation to make up <span class="hljs-keyword">for</span> the slightly lower precipitation levels this month. Aim to maintain soil moisture at <span class="hljs-number">60</span><span class="hljs-number">-70</span>% to support optimal growth during the reproductive phase of the corn crop.
- Regular monitoring of soil moisture <span class="hljs-keyword">and</span> weather conditions <span class="hljs-keyword">is</span> crucial to adjust irrigation <span class="hljs-keyword">and</span> nutrient inputs dynamically throughout the season.
</code></pre>
<p><a target="_blank" href="https://lunartech.ai"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725976804136/c7b556e9-c4c4-4264-b78a-0197335564f1.png" alt="A terminal window displays text about a corn crop yield forecast and suggestions for improving yield. The temperature is 28°C, slightly lower-than-optimal precipitation level of 90mm, with a projected yield of 4800 kg/hectare. Soil moisture supports healthy growth at 50%. Recommendations include increasing irrigation and monitoring soil moisture and weather conditions. - lunartech.ai" class="image--center mx-auto" width="2048" height="782" loading="lazy"></a></p>
<p><strong>In Example 1</strong>, we used LLMs to analyze large datasets from sensors, satellite imagery, and weather forecasts to provide irrigation and fertilization schedules, ensuring that crops receive the right amount of water and nutrients.</p>
<p><strong>In Example 2</strong>, you learned how LLMs can interpret data from drone-based computer vision systems to detect signs of water stress, nutrient deficiencies, and potential diseases. The model generates targeted interventions to improve crop health.</p>
<p><strong>And in Example 3</strong>, we used LLMs to process historical and real-time data to forecast crop yields and recommend adjustments to optimize yield, such as increasing irrigation or adjusting nutrient levels based on environmental factors.</p>
<p>In all three examples, LLMs helped process complex data and provide actionable insights for farmers, supporting decisions that improve crop yields, sustainability, and resource efficiency.</p>
<p>The integration of big data and computer vision technologies is undeniably transforming agriculture, making it more efficient, sustainable, and resilient. By leveraging these advanced tools, farmers are better equipped to navigate the complexities of modern farming, addressing challenges such as climate variability, resource limitations, and the need for increased productivity.</p>
<h2 id="heading-chapter-6-optimizing-soil-moisture-and-quality-with-ai-models">Chapter 6: Optimizing Soil Moisture and Quality with AI Models</h2>
<h3 id="heading-the-importance-of-soil-moisture-management"><strong>The Importance of Soil Moisture Management</strong></h3>
<p>Effective soil moisture management is fundamental for optimizing crop yields, a goal that resonates universally within the agricultural sector. Inadequate or excessive moisture levels can lead to various complications like root diseases, nutrient leaching, and even yield reduction.</p>
<p>As AI-integrated farming techniques become more sophisticated, they offer a seamless solution to these age-old problems. By employing AI models, farmers can ensure crops consistently receive just the right amount of water.</p>
<p>A powerful aspect of these AI models is their ability to monitor and interpret various data points in real-time, providing insights that would be impossible through manual methods. For instance, imagine a system that analyzes weather forecasts, soil types, and plant needs daily, adjusting irrigation schedules to match this dynamic environment precisely. It's like having a digital agronomist tirelessly working to keep your soil in perfect condition. This heightened level of precision translates directly to higher yields and better crop health.</p>
<p>Not only does this help issue-specific concerns like drought or over-irrigation, but it also integrates seamlessly into larger farm management systems. By identifying optimal times for water distribution, AI allows for more strategic planning and resource allocation. Think of it as a cycle: healthier soil leads to healthier crops, requiring even less intervention. Thus, the benefits cascade, leading to more efficient and sustainable farming practices.</p>
<h3 id="heading-benefits-of-ai-in-optimizing-soil-quality"><strong>Benefits of AI in Optimizing Soil Quality</strong></h3>
<p>One of the most compelling advantages of using artificial intelligence in soil quality optimization is its precision. Traditional farming often relies on blanket treatments—broadly applying water or fertilizer across entire fields. AI transforms this into a surgical procedure, tailored to the specific needs of different soil segments.</p>
<p>For example, a farmer might employ an AI model to identify that a particular section of a field is nutrient-deficient. Rather than fertilizing the entire field, resources can be directed precisely where they are needed most.</p>
<p>Predictive analytics represent another revolutionary facet of AI, eliminating the guesswork from farming. By analyzing a rich history of data—soil tests, weather conditions, crop performance—AI enables farmers to anticipate future conditions and prepare accordingly. This kind of foresight can be invaluable when planning crop rotations, anticipating pest invasions, or deciding on the optimal planting and harvesting times. Imagine having a crystal ball that tells you exactly when to plant each year, aligning perfectly with the best-growing conditions.</p>
<p>The key takeaway here is that AI can help provide sustainable solutions. As AI models become more sophisticated, their ability to adapt to changing climates and soil conditions grows, providing a robust platform for future farming endeavors. In this way, AI-enabled soil quality management systems are contributing towards global food security, a critical need underscored in discussions on agricultural advancements.</p>
<h3 id="heading-integration-with-existing-farming-practices"><strong>Integration with Existing Farming Practices</strong></h3>
<p>The integration of AI into existing farming practices should be seamless, enhancing rather than disrupting daily operations. Many farmers may be wary of adopting new technologies, fearing complexity or disruption. But today's AI systems are designed for usability. They often integrate directly with existing farm management software, providing a unified interface for all your agricultural needs. For example, systems like John Deere's Operations Center offer modules that incorporate AI-driven insights into traditional farm management tools.</p>
<p>Farmers can see real-time data on soil moisture levels, nutrient content, and irrigation needs, all in one place. These platforms often offer mobile applications, allowing farmers to access this critical information from anywhere, making decisions on-the-go. The ease of use and accessibility of AI models demystify the technology, making it more approachable. It's not about replacing the farmer's expertise but augmenting it—providing tools that enable smarter, more efficient farming.</p>
<p>Full integration into irrigation systems means the AI can automatically adjust water levels without manual intervention. This automation ensures that even the minutest changes in soil conditions are addressed immediately, maintaining optimal growing conditions at all times. Think of it as a smart home system but for your crops—a digital assistant that ensures everything runs smoothly, even when you cannot be present.</p>
<h3 id="heading-balancing-technological-advancements-and-practical-applications"><strong>Balancing Technological Advancements and Practical Applications</strong></h3>
<p>While the promise of AI in optimizing soil moisture and quality is enormous, its practical application requires a balanced approach. Not all farms are the same, and the variance in soil types, climate conditions, and crop types means a one-size-fits-all solution isn’t feasible.</p>
<p>Tailoring AI models to fit specific needs is crucial for maximizing their effectiveness. Customizable AI platforms are gaining traction because they allow for this level of specificity.</p>
<p>Take, for instance, a farm situated in a semi-arid region. The soil here typically has lower organic content and higher salinity levels. An AI model geared towards this specific environment will focus on conserving water while improving soil quality through targeted fertilization techniques and organic amendments.</p>
<p>Contrast this with a farm in a temperate climate, where the AI might prioritize managing periodic heavy rains to prevent soil erosion and nutrient loss. The customization of AI applications ensures that solutions are relevant and effective, driving meaningful improvements in any farming context.</p>
<p>The interdisciplinary nature of AI-powered farming highlights the need for collaboration between technology developers, agronomists, and the farmers themselves. Each stakeholder brings invaluable expertise, and their combined efforts can overcome any initial hurdles.</p>
<p>Training programs and workshops can further this integration, empowering farmers to use these technologies effectively. Enhancing the farmers' understanding of how these tools work allows them to make more informed decisions, unlocking the full potential of AI in agriculture.</p>
<h3 id="heading-addressing-challenges-and-ethical-considerations"><strong>Addressing Challenges and Ethical Considerations</strong></h3>
<p>As with any technological advancement, the implementation of AI in soil moisture and quality management comes with its own set of challenges. One significant concern is data privacy. Farms collect vast amounts of data—weather conditions, soil properties, crop performance—that is valuable not just to farmers but to numerous stakeholders, including corporations and governments. Ensuring this data is used ethically and remains secure is paramount.</p>
<p>Another challenge is accessibility. While larger, well-funded farms can afford to implement advanced AI systems, smaller farms often operate on tighter budgets. Ensuring equitable access to this transformative technology is crucial for its widespread adoption. Public funding, subsidies, and collaborative efforts between private sectors and government bodies can create pathways for smaller farms to benefit from AI advancements.</p>
<p>While AI systems can alleviate many manual tasks, reliance on technology should not come at the expense of traditional farming knowledge. The wisdom and experience of seasoned farmers offer insights that cannot be wholly replicated by algorithms. Thus, a balanced approach that combines the best of both worlds—traditional agriculture knowledge and modern AI capabilities—will yield the most robust, sustainable farming practices.</p>
<h3 id="heading-towards-sustainable-and-resilient-agriculture"><strong>Towards Sustainable and Resilient Agriculture</strong></h3>
<p>The future of agriculture lies in leveraging technological advancements like AI to create systems that are not only high-yielding but also sustainable and resilient. AI-powered soil moisture and quality management systems offer a glimpse into this future, where data-driven decisions replace guesswork, and precise interventions lead to optimal outcomes. The cascading benefits—from increased crop yields and reduced resource use to enhanced food security—highlight the immense potential of this approach.</p>
<p>The adoption of these AI models is an essential step towards realizing the goals set out in AI in Agriculture: How AI-Enhanced Farming Could Increase Crop Yields by 70% by 2030. With every farm that integrates AI technology, we get closer to a world where agricultural practices are sustainable, efficient, and resilient to the challenges posed by climate change and growing populations.</p>
<h4 id="heading-code-examples-2">Code Examples</h4>
<p>Below are advanced examples of how Large Language Models (LLMs) can be incorporated into AI models for optimizing soil moisture and quality management in agriculture. These examples align well with the ones from the chapter on <strong>optimizing soil moisture and quality.</strong></p>
<h4 id="heading-example-1-ai-driven-real-time-soil-moisture-management"><strong>Example 1: AI-driven real-time soil moisture management</strong></h4>
<p><strong>Objective:</strong> Use an LLM to dynamically adjust irrigation schedules based on soil moisture sensor data, weather forecasts, and crop needs. The system optimizes water distribution in real-time, considering potential root diseases and nutrient leaching.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

<span class="hljs-comment"># Sample input data from real-time sensors and weather forecasts</span>
soil_data = {
    <span class="hljs-string">"moisture_level"</span>: <span class="hljs-number">40</span>,  <span class="hljs-comment"># Soil moisture percentage</span>
    <span class="hljs-string">"root_zone_temperature"</span>: <span class="hljs-number">25</span>,  <span class="hljs-comment"># Temperature in Celsius</span>
    <span class="hljs-string">"potential_root_disease_risk"</span>: <span class="hljs-string">"moderate"</span>
}

weather_forecast = {
    <span class="hljs-string">"today"</span>: {<span class="hljs-string">"temp"</span>: <span class="hljs-number">30</span>, <span class="hljs-string">"humidity"</span>: <span class="hljs-number">60</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">5</span>},  <span class="hljs-comment"># °C, %, mm</span>
    <span class="hljs-string">"tomorrow"</span>: {<span class="hljs-string">"temp"</span>: <span class="hljs-number">32</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">10</span>}  <span class="hljs-comment"># °C, mm</span>
}

crop_needs = {
    <span class="hljs-string">"growth_stage"</span>: <span class="hljs-string">"flowering"</span>,
    <span class="hljs-string">"water_requirement"</span>: <span class="hljs-string">"high"</span>
}

<span class="hljs-comment"># Describe the current data to the LLM</span>
data_description = (
    <span class="hljs-string">f"The current soil moisture level is <span class="hljs-subst">{soil_data[<span class="hljs-string">'moisture_level'</span>]}</span>%. "</span>
    <span class="hljs-string">f"Root zone temperature is <span class="hljs-subst">{soil_data[<span class="hljs-string">'root_zone_temperature'</span>]}</span>°C. "</span>
    <span class="hljs-string">f"There is a <span class="hljs-subst">{soil_data[<span class="hljs-string">'potential_root_disease_risk'</span>]}</span> risk of root disease. "</span>
    <span class="hljs-string">f"Today's weather forecast shows a temperature of <span class="hljs-subst">{weather_forecast[<span class="hljs-string">'today'</span>][<span class="hljs-string">'temp'</span>]}</span>°C "</span>
    <span class="hljs-string">f"with 5mm of precipitation and 60% humidity. The crop is in the flowering stage, "</span>
    <span class="hljs-string">f"and its water requirement is high."</span>
)

<span class="hljs-comment"># Use an LLM to adjust the irrigation schedule based on real-time data</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an AI expert specializing in soil moisture management and irrigation."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following data, provide an optimized irrigation schedule: <span class="hljs-subst">{data_description}</span>"</span>}
    ]
)

irrigation_schedule = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(irrigation_schedule)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725977544594/041ab26f-16ce-4d2b-8622-2c9c2212a444.png" alt="041ab26f-16ce-4d2b-8622-2c9c2212a444" class="image--center mx-auto" width="2048" height="1972" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Optimized Irrigation Schedule:**
- Given the current soil moisture level of <span class="hljs-number">40</span>%, irrigation should be scheduled <span class="hljs-keyword">for</span> early tomorrow morning, especially considering the high water requirement during the flowering stage.
- With <span class="hljs-number">5</span>mm of precipitation expected today <span class="hljs-keyword">and</span> <span class="hljs-number">10</span>mm tomorrow, delay any additional irrigation until after the forecasted rain, <span class="hljs-keyword">and</span> reassess moisture levels.
- Monitor root zone temperature <span class="hljs-keyword">and</span> soil moisture closely over the next <span class="hljs-number">24</span> hours to avoid overwatering, which could exacerbate the moderate risk of root disease. Ensure that irrigation <span class="hljs-keyword">is</span> balanced to prevent nutrient leaching.
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725977593380/5fe0c0c6-f0e0-4f85-88ea-a1beb5c28c6f.png" alt="A black terminal window with a refined irrigation schedule. The current soil moisture level is 40%. 5 mm of precipitation is expected today and 10 mm tomorrow. Irrigation is recommended for early tomorrow morning, delaying additional irrigation until after the rain. Monitor soil conditions closely over the next 24 hours to avoid overwatering and prevent nutrient leaching. - lunartech.ai" class="image--center mx-auto" width="2048" height="670" loading="lazy"></a></p>
<h4 id="heading-example-2-ai-enhanced-soil-quality-analysis-and-fertilization-strategy"><strong>Example 2: AI-enhanced soil quality analysis and fertilization strategy</strong></h4>
<p><strong>Objective:</strong> Use an LLM to analyze soil quality based on nutrient levels and crop requirements. The system recommends precise fertilization strategies based on real-time and historical data, helping avoid over-fertilization and nutrient leaching.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample input data from soil tests and crop requirements</span>
soil_data = {
    <span class="hljs-string">"pH"</span>: <span class="hljs-number">6.5</span>,
    <span class="hljs-string">"nutrient_levels"</span>: {<span class="hljs-string">"nitrogen"</span>: <span class="hljs-number">30</span>, <span class="hljs-string">"phosphorus"</span>: <span class="hljs-number">15</span>, <span class="hljs-string">"potassium"</span>: <span class="hljs-number">25</span>},  <span class="hljs-comment"># ppm</span>
    <span class="hljs-string">"organic_matter"</span>: <span class="hljs-number">3.0</span>  <span class="hljs-comment"># percentage</span>
}

crop_data = {
    <span class="hljs-string">"crop_type"</span>: <span class="hljs-string">"wheat"</span>,
    <span class="hljs-string">"growth_stage"</span>: <span class="hljs-string">"early vegetative"</span>,
    <span class="hljs-string">"nutrient_requirement"</span>: {<span class="hljs-string">"nitrogen"</span>: <span class="hljs-string">"high"</span>, <span class="hljs-string">"phosphorus"</span>: <span class="hljs-string">"moderate"</span>, <span class="hljs-string">"potassium"</span>: <span class="hljs-string">"low"</span>}
}

<span class="hljs-comment"># Generate description for the LLM based on the input data</span>
data_description = (
    <span class="hljs-string">f"The soil pH is <span class="hljs-subst">{soil_data[<span class="hljs-string">'pH'</span>]}</span>, and the nutrient levels are nitrogen at <span class="hljs-subst">{soil_data[<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'nitrogen'</span>]}</span> ppm, "</span>
    <span class="hljs-string">f"phosphorus at <span class="hljs-subst">{soil_data[<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'phosphorus'</span>]}</span> ppm, and potassium at <span class="hljs-subst">{soil_data[<span class="hljs-string">'nutrient_levels'</span>][<span class="hljs-string">'potassium'</span>]}</span> ppm. "</span>
    <span class="hljs-string">f"The organic matter content is <span class="hljs-subst">{soil_data[<span class="hljs-string">'organic_matter'</span>]}</span>%. The crop type is wheat, which is in the early vegetative stage and has high nitrogen requirements."</span>
)

<span class="hljs-comment"># Use LLM to generate a precise fertilization strategy</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an AI agronomist specializing in soil quality and fertilization."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following soil and crop data, provide a fertilization strategy: <span class="hljs-subst">{data_description}</span>"</span>}
    ]
)

fertilization_strategy = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(fertilization_strategy)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725977665700/d16ce88a-20b9-4fd8-bc4b-088850dc0424.png" alt="A screenshot of Python code using the OpenAI API to generate a fertilization strategy based on soil and crop data. The code imports the OpenAI library, defines sample input data for soil and crop requirements, constructs a descriptive message for the AI model, and requests a fertilization strategy from the AI. The strategy is then printed out. - lunartech.ai" class="image--center mx-auto" width="2048" height="1786" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Fertilization Strategy:**
- **Nitrogen:** The current nitrogen level <span class="hljs-keyword">is</span> <span class="hljs-number">30</span> ppm, which <span class="hljs-keyword">is</span> below the optimal range <span class="hljs-keyword">for</span> wheat <span class="hljs-keyword">in</span> the early vegetative stage. Apply a nitrogen-rich fertilizer, such <span class="hljs-keyword">as</span> urea, at a rate of <span class="hljs-number">50</span> kg/ha to meet the high nitrogen demands.

- **Phosphorus:** Phosphorus levels are moderately low at <span class="hljs-number">15</span> ppm. Apply phosphorus-based fertilizer, such <span class="hljs-keyword">as</span> triple superphosphate, at a rate of <span class="hljs-number">25</span> kg/ha to support early root development.

- **Potassium:** Potassium levels are sufficient <span class="hljs-keyword">for</span> this stage, so no additional potassium fertilization <span class="hljs-keyword">is</span> needed at this time.

- Monitor the soil pH to ensure it remains within the optimal range <span class="hljs-keyword">for</span> wheat growth (<span class="hljs-number">6.0</span><span class="hljs-number">-7.0</span>). If pH begins to drop below <span class="hljs-number">6.0</span>, consider applying lime to balance the soil acidity.
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725977726308/298d7844-a6bb-4459-968a-4ceb55f84f3a.png" alt="Screenshot of a fertilization strategy for wheat. It details the current nutrient levels:- Nitrogen: 30 ppm, below optimal. Apply nitrogen-rich fertilizer at 50 kg/ha.- Phosphorus: 15 ppm, moderately low. Apply phosphorus-based fertilizer at 25 kg/ha.- Potassium: Sufficient, no additional fertilization needed.Also, monitor soil pH to keep it within 6.0-7.0. Apply lime if pH drops below 6.0. - lunartech.ai" class="image--center mx-auto" width="2048" height="856" loading="lazy"></a></p>
<h4 id="heading-example-3-ai-powered-predictive-analytics-for-soil-moisture-and-quality-optimization"><strong>Example 3: AI-powered predictive analytics for soil moisture and quality optimization</strong></h4>
<p><strong>Objective:</strong> Use an LLM to combine predictive analytics and historical data to forecast future soil moisture conditions, nutrient levels, and irrigation needs. The AI provides a long-term soil management strategy based on weather predictions and crop growth stages.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> datetime

<span class="hljs-comment"># Historical and predictive input data for AI analysis</span>
historical_data = {
    <span class="hljs-string">"soil_moisture_trend"</span>: [<span class="hljs-number">40</span>, <span class="hljs-number">35</span>, <span class="hljs-number">30</span>, <span class="hljs-number">25</span>],  <span class="hljs-comment"># % moisture over past 4 weeks</span>
    <span class="hljs-string">"nutrient_depletion"</span>: {<span class="hljs-string">"nitrogen"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"phosphorus"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"potassium"</span>: <span class="hljs-number">0.5</span>},  <span class="hljs-comment"># ppm depletion rate per week</span>
    <span class="hljs-string">"weather_trends"</span>: [
        {<span class="hljs-string">"week"</span>: <span class="hljs-number">1</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">20</span>},  <span class="hljs-comment"># mm of rain</span>
        {<span class="hljs-string">"week"</span>: <span class="hljs-number">2</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">10</span>},
        {<span class="hljs-string">"week"</span>: <span class="hljs-number">3</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">0</span>},
        {<span class="hljs-string">"week"</span>: <span class="hljs-number">4</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">5</span>}
    ]
}

current_conditions = {
    <span class="hljs-string">"soil_moisture"</span>: <span class="hljs-number">30</span>,  <span class="hljs-comment"># current soil moisture percentage</span>
    <span class="hljs-string">"weather_forecast"</span>: {<span class="hljs-string">"next_week_precipitation"</span>: <span class="hljs-number">15</span>},  <span class="hljs-comment"># mm of expected rain</span>
    <span class="hljs-string">"growth_stage"</span>: <span class="hljs-string">"mid-vegetative"</span>
}

<span class="hljs-comment"># Generate description for the LLM</span>
data_description = (
    <span class="hljs-string">f"Over the past 4 weeks, soil moisture has decreased from 40% to 25%. Nitrogen has been depleting at a rate of 2 ppm per week. "</span>
    <span class="hljs-string">f"The precipitation levels have been fluctuating, with only 5mm last week and 15mm expected next week. "</span>
    <span class="hljs-string">f"The crop is currently in the mid-vegetative stage."</span>
)

<span class="hljs-comment"># Use LLM to provide long-term soil moisture and quality optimization strategy</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an AI agronomist specializing in predictive analytics for soil moisture and quality."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following historical and predictive data, provide a soil moisture and quality management strategy: <span class="hljs-subst">{data_description}</span>"</span>}
    ]
)

soil_management_strategy = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(soil_management_strategy)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725977788352/70065954-b5ff-4dfb-884a-5f1d94449528.png" alt="A screenshot of a Python script using OpenAI's API to generate a description of soil moisture and weather trends. The script imports required libraries, prepares historical data on soil moisture and nutrient depletion, sets current soil conditions, and defines a prompt for the AI model to generate a long-term soil management strategy based on the provided data. The script finally prints the generated soil management strategy. - lunartech.ai" class="image--center mx-auto" width="2048" height="2010" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-markdown"><span class="hljs-strong">**Soil Moisture and Quality Management Strategy**</span>

Based on the historical data and current conditions, the following strategy is recommended to optimize soil moisture and maintain soil quality:

<span class="hljs-bullet">1.</span> <span class="hljs-strong">**Irrigation Management**</span>
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Scheduled Irrigation:**</span> Implement a drip irrigation system to provide consistent moisture levels, targeting a soil moisture percentage between 30% and 35%. This helps compensate for the recent decline from 40% to 25%.
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Rainfall Utilization:**</span> With an expected 15mm of precipitation next week, adjust the irrigation schedule to reduce water input accordingly, preventing waterlogging and conserving water resources.

<span class="hljs-bullet">2.</span> <span class="hljs-strong">**Nutrient Management**</span>
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Nitrogen Supplementation:**</span> Given the depletion rate of 2 ppm per week, apply a nitrogen-rich fertilizer bi-weekly to replenish soil nitrogen levels and support plant growth during the mid-vegetative stage.
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Phosphorus and Potassium Maintenance:**</span> Continue monitoring phosphorus and potassium levels, applying supplements as needed to maintain balanced nutrient availability.

<span class="hljs-bullet">3.</span> <span class="hljs-strong">**Soil Conservation Practices**</span>
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Mulching:**</span> Apply organic mulch around crops to reduce soil evaporation, maintain moisture levels, and improve soil structure.
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Cover Cropping:**</span> Introduce cover crops during off-seasons to enhance soil organic matter, prevent erosion, and improve nutrient retention.

<span class="hljs-bullet">4.</span> <span class="hljs-strong">**Weather Adaptation**</span>
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Drainage Management:**</span> Ensure proper drainage systems are in place to handle the variability in precipitation, especially during weeks with low rainfall.
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Weather Monitoring:**</span> Utilize weather forecasting tools to make informed decisions on irrigation and nutrient application, adapting strategies based on real-time data.

<span class="hljs-bullet">5.</span> <span class="hljs-strong">**Crop Management**</span>
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Growth Stage Optimization:**</span> During the mid-vegetative stage, focus on practices that support robust leaf and stem development, ensuring that soil conditions do not limit plant growth.
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Pest and Disease Monitoring:**</span> Regularly inspect crops for signs of stress, pests, or diseases that may arise from fluctuating soil moisture and nutrient levels.

<span class="hljs-bullet">6.</span> <span class="hljs-strong">**Long-Term Soil Health**</span>
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Soil Testing:**</span> Conduct quarterly soil tests to monitor nutrient levels, pH, and organic matter content, allowing for data-driven adjustments to management practices.
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Sustainable Practices:**</span> Invest in sustainable farming practices such as crop rotation and reduced tillage to enhance soil health and resilience against environmental stressors.

<span class="hljs-bullet">7.</span> <span class="hljs-strong">**Technology Integration**</span>
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Soil Moisture Sensors:**</span> Deploy soil moisture sensors to obtain real-time data, enabling precise irrigation control and timely interventions.
<span class="hljs-bullet">   -</span> <span class="hljs-strong">**Data Analytics:**</span> Utilize data analytics platforms to track historical trends and predict future soil moisture and nutrient needs, optimizing resource allocation.

<span class="hljs-strong">**Implementation Timeline:**</span>
<span class="hljs-bullet">-</span> <span class="hljs-strong">**Immediate (Next 1-2 Weeks):**</span>
<span class="hljs-bullet">  -</span> Install or calibrate drip irrigation systems.
<span class="hljs-bullet">  -</span> Apply nitrogen-based fertilizers.
<span class="hljs-bullet">  -</span> Begin mulching around crop areas.

<span class="hljs-bullet">-</span> <span class="hljs-strong">**Short-Term (Next 1-3 Months):**</span>
<span class="hljs-bullet">  -</span> Monitor soil moisture and nutrient levels weekly.
<span class="hljs-bullet">  -</span> Adjust irrigation schedules based on rainfall and sensor data.
<span class="hljs-bullet">  -</span> Introduce cover crops during off-seasons.

<span class="hljs-bullet">-</span> <span class="hljs-strong">**Long-Term (6 Months - 1 Year):**</span>
<span class="hljs-bullet">  -</span> Conduct comprehensive soil health assessments.
<span class="hljs-bullet">  -</span> Implement sustainable farming practices.
<span class="hljs-bullet">  -</span> Invest in advanced soil monitoring technologies.

By following this strategy, you can effectively manage soil moisture levels, replenish essential nutrients, and maintain overall soil health, leading to sustained crop productivity and resilience against environmental challenges.
</code></pre>
<h2 id="heading-chapter-7-sustainable-land-use-strategies-with-agricultural-technology">Chapter 7: Sustainable Land Use Strategies with Agricultural Technology</h2>
<p>In the landscape of modern agriculture, the promise of AI-enhanced farming sets a compelling context for exploring sustainable land use strategies supported by technological advancements.</p>
<p>The confluence of artificial intelligence and sustainable agricultural practices not only addresses the need for increased productivity but also emphasizes the importance of environmental stewardship.</p>
<p>This chapter delves into how the integration of AI and other cutting-edge technologies can revolutionize land use, optimizing resource management while promoting ecological balance.</p>
<h3 id="heading-precision-agriculture-for-resource-optimization"><strong>Precision Agriculture for Resource Optimization</strong></h3>
<p>Precision agriculture, a hallmark of modern farming, leverages AI models and predictive analytics to refine agricultural practices at an unprecedented scale. By employing advanced data analytics, farmers can monitor vital parameters such as soil conditions, weather patterns, and crop health with pinpoint accuracy.</p>
<p>For example, soil moisture sensors connected to AI platforms can provide real-time data, enabling farmers to optimize irrigation schedules to conserve water without compromising crop health.</p>
<p>This level of precision empowers farmers to tailor their use of fertilizers and pesticides, reducing waste and enhancing soil quality. AI-driven soil quality assessments can guide the application of nutrients specifically where they are needed, rather than blanket coverage, which can lead to pollution and soil degradation. By focusing on data-driven decisions, precision agriculture not only enhances yield but also aligns farming practices with sustainable land management.</p>
<h3 id="heading-ai-powered-farm-management-software"><strong>AI-Powered Farm Management Software</strong></h3>
<p>AI-powered farm management software represents the next frontier in agricultural efficiency. These platforms offer comprehensive tools to streamline farm operations, from resource allocation to day-to-day task management. The integration of computer vision technology allows for early detection of crop anomalies, such as nutrient deficiencies or pest infestations, through the analysis of high-resolution images.</p>
<p>This proactive approach can significantly mitigate crop losses and minimize the need for chemical interventions, thus fostering more sustainable farming practices. Moreover, robotic process automation (RPA) addresses labor shortages by automating routine tasks such as planting, weeding, and harvesting. This not only reduces operational strain but also enables farmers to focus on strategic decision-making and long-term planning.</p>
<h3 id="heading-sustainable-practices-for-enhanced-yields"><strong>Sustainable Practices for Enhanced Yields</strong></h3>
<p>Sustainable agricultural practices supported by AI technologies embrace the dual goals of maximizing productivity and minimizing environmental impact. AI-powered precision irrigation systems, for example, use weather forecasts and soil moisture data to deliver water only when and where it is needed. This not only conserves water but also ensures that crops receive optimal hydration for maximum growth.</p>
<p>Also, the adoption of AI solutions for sustainable land use often comes with financial incentives. Governments and international bodies increasingly recognize the importance of sustainable farming and offer subsidies or grants to farmers who implement eco-friendly technologies. These incentives not only offset the initial cost of adopting new technologies but also promote long-term benefits such as improved soil health, reduced pollution, and enhanced biodiversity.</p>
<h3 id="heading-embracing-the-future-of-agriculture-with-ai"><strong>Embracing the Future of Agriculture with AI</strong></h3>
<p>The future of agriculture lies in the seamless integration of AI technologies, transforming traditional farming into a sophisticated, data-driven practice. By addressing critical challenges such as climate variability, labor shortages, and resource constraints, AI technologies ensure the resilience and sustainability of the global food system.</p>
<p>For example, machine learning algorithms can predict climate-related risks, allowing farmers to adapt their planting schedules and crop selections accordingly. This adaptive approach is essential in a world where climate change poses an increasing threat to food security. By leveraging AI, farmers can make informed decisions that not only enhance productivity but also safeguard the environment for future generations.</p>
<h3 id="heading-optimizing-resource-management-through-precision-agriculture"><strong>Optimizing Resource Management through Precision Agriculture</strong></h3>
<p>Precision agriculture stands at the forefront of resource management optimization. Through the use of AI models and big data analytics, farmers can monitor and manage resources with precision, leading to significant improvements in efficiency and sustainability.</p>
<p>Soil moisture sensors are a prime example of technology enabling precise irrigation management. These sensors provide real-time data on soil moisture levels, helping farmers determine the exact amount of water needed. This ensures optimal crop hydration, reduces water wastage, and prevents over-irrigation, which can lead to soil erosion and nutrient runoff.</p>
<p>Beyond irrigation, precision agriculture plays a vital role in managing soil quality. AI-powered tools analyze soil samples to assess nutrient levels and composition. Farmers can then tailor fertilizer application to the specific needs of different soil sections, avoiding overuse and minimizing environmental impact. This targeted approach not only enhances crop yield but also promotes soil health and reduces the risk of contamination in nearby water sources.</p>
<p>The integration of weather pattern analysis further enhances resource management. Predictive analytics can forecast weather conditions with high accuracy, allowing farmers to plan their activities accordingly. Whether it's adjusting planting schedules to avoid adverse weather or applying protective measures against frost or drought, precision agriculture empowers farmers to make informed decisions that optimize resource use.</p>
<h3 id="heading-enhancing-farm-efficiency-with-ai-technologies"><strong>Enhancing Farm Efficiency with AI Technologies</strong></h3>
<p>One of the most significant contributions of AI to agriculture is the development of advanced farm management software. These platforms leverage AI algorithms to streamline farm operations, resulting in increased efficiency and productivity. By tracking and managing resources such as labor, equipment, and inputs, these systems offer a holistic view of farm activities.</p>
<p>Computer vision technology, integrated into farm management software, provides farmers with invaluable insights into crop health. High-resolution images captured by drones or sensors undergo detailed analysis, enabling early detection of issues such as nutrient deficiencies, pest infestations, or disease outbreaks. Timely intervention can prevent these problems from spreading and causing extensive damage. And AI-powered recommendation engines suggest appropriate remedial actions, empowering farmers to address issues effectively.</p>
<p>Robotic process automation (RPA) is another key component in enhancing farm efficiency. Automation of repetitive and labor-intensive tasks such as planting, weeding, and harvesting not only reduces the reliance on human labor but also ensures precision and consistency. This, in turn, leads to higher productivity and reduced operational costs.</p>
<h3 id="heading-promoting-sustainable-farming-practices-with-ai"><strong>Promoting Sustainable Farming Practices with AI</strong></h3>
<p>Sustainable land use practices are integral to achieving long-term agricultural productivity while minimizing environmental impact. AI technologies play a pivotal role in promoting these practices by optimizing land use and conserving natural resources. Precision irrigation systems, powered by AI, exemplify the synergy between technology and sustainability. By delivering water precisely when and where it is needed, these systems reduce water wastage and ensure that crops receive optimal hydration.</p>
<p>AI-driven solutions for nutrient management also help contribute to sustainable farming by minimizing the use of chemical fertilizers. By analyzing soil nutrient levels, AI models recommend targeted fertilization, ensuring that nutrients are applied only where required. This not only enhances crop yield but also prevents over-fertilization, which can lead to soil and water pollution.</p>
<p>Fuel consumption is another significant area where AI can drive sustainability. Autonomous machinery equipped with AI algorithms optimizes fuel use by planning efficient routes and minimizing idle time. This reduces greenhouse gas emissions and lowers operational costs, contributing to both environmental and economic sustainability.</p>
<h3 id="heading-financial-incentives-for-sustainable-farming"><strong>Financial Incentives for Sustainable Farming</strong></h3>
<p>The adoption of sustainable land use strategies is often facilitated by financial incentives provided by governments and organizations. These incentives encourage farmers to invest in AI-driven technologies that promote sustainability and long-term benefits. Subsidies, grants, and tax incentives help offset the initial costs of implementing new technologies, making them more accessible to farmers.</p>
<p>For instance, governments may offer subsidies for the installation of precision irrigation systems or provide grants for adopting AI-powered soil analysis tools. These financial incentives not only support the transition to sustainable farming practices but also recognize the broader societal benefits, such as improved water quality, reduced greenhouse gas emissions, and enhanced biodiversity.</p>
<p>Sustainable farming practices driven by AI technologies can also lead to increased profitability for farmers. By optimizing resource use, reducing input costs, and enhancing crop yield, these practices contribute to higher economic returns. Farmers who embrace AI-driven solutions are better positioned to achieve long-term financial stability while contributing to a more sustainable food system.</p>
<h3 id="heading-building-a-resilient-future-with-ai-in-agriculture"><strong>Building a Resilient Future with AI in Agriculture</strong></h3>
<p>The integration of AI technologies in agriculture represents a paradigm shift that addresses critical challenges and paves the way for a resilient and sustainable future. By harnessing the power of AI, farmers can navigate the complexities of modern farming, optimize resource use, and mitigate environmental impact.</p>
<p>AI-driven predictive analytics empower farmers to adapt to changing climatic conditions. By analyzing historical weather data and current trends, AI models can predict future weather patterns with high precision. This enables farmers to make proactive decisions, such as adjusting planting schedules, selecting resilient crop varieties, and implementing protective measures. Such adaptive strategies are essential in the face of climate change, ensuring the continuity of agricultural productivity.</p>
<p>Labor shortages, a persistent challenge in agriculture, are effectively addressed by AI-powered automation. Robots and autonomous machinery perform labor-intensive tasks with precision and reliability, reducing the dependence on human labor. This not only increases operational efficiency but also allows farmers to focus on strategic planning and innovation.</p>
<h4 id="heading-code-examples-3">Code Examples</h4>
<p>Here are three advanced examples of how Large Language Models (LLMs) can be integrated into AI technologies to enhance <strong>Sustainable Land Use Strategies with Agricultural Technology</strong>:</p>
<h4 id="heading-example-1-ai-driven-precision-agriculture-for-resource-optimization"><strong>Example 1: AI-driven precision agriculture for resource optimization</strong></h4>
<p><strong>Objective:</strong> Use LLM to analyze data from soil sensors, satellite imagery, and weather forecasts to optimize irrigation and fertilizer use while maintaining sustainability. This example will help farmers optimize resource use, reduce environmental impact, and promote sustainable land management.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample input data from soil sensors, satellite imagery, and weather forecasts</span>
farm_data = {
    <span class="hljs-string">"soil_moisture"</span>: {
        <span class="hljs-string">"zone_A"</span>: <span class="hljs-number">45</span>,  <span class="hljs-comment"># percentage</span>
        <span class="hljs-string">"zone_B"</span>: <span class="hljs-number">30</span>,  <span class="hljs-comment"># percentage</span>
    },
    <span class="hljs-string">"satellite_imagery"</span>: {
        <span class="hljs-string">"vegetation_health_index"</span>: <span class="hljs-number">0.85</span>,  <span class="hljs-comment"># normalized between 0 to 1</span>
    },
    <span class="hljs-string">"weather_forecast"</span>: {
        <span class="hljs-string">"today"</span>: {<span class="hljs-string">"temperature"</span>: <span class="hljs-number">28</span>, <span class="hljs-string">"humidity"</span>: <span class="hljs-number">65</span>, <span class="hljs-string">"precipitation"</span>: <span class="hljs-number">3</span>},  <span class="hljs-comment"># in °C, %, mm</span>
        <span class="hljs-string">"next_week_precipitation"</span>: <span class="hljs-number">15</span>,  <span class="hljs-comment"># mm of rain expected over the next week</span>
    }
}

<span class="hljs-comment"># Describe data for LLM input</span>
data_summary = (
    <span class="hljs-string">f"Zone A soil moisture is at <span class="hljs-subst">{farm_data[<span class="hljs-string">'soil_moisture'</span>][<span class="hljs-string">'zone_A'</span>]}</span>%, while Zone B is at <span class="hljs-subst">{farm_data[<span class="hljs-string">'soil_moisture'</span>][<span class="hljs-string">'zone_B'</span>]}</span>%. "</span>
    <span class="hljs-string">f"The satellite imagery shows a vegetation health index of <span class="hljs-subst">{farm_data[<span class="hljs-string">'satellite_imagery'</span>][<span class="hljs-string">'vegetation_health_index'</span>]}</span>. "</span>
    <span class="hljs-string">f"Today's weather forecast indicates a temperature of <span class="hljs-subst">{farm_data[<span class="hljs-string">'weather_forecast'</span>][<span class="hljs-string">'today'</span>][<span class="hljs-string">'temperature'</span>]}</span>°C, "</span>
    <span class="hljs-string">f"with 65% humidity and 3mm precipitation. The forecasted rainfall for the next week is 15mm."</span>
)

<span class="hljs-comment"># Use LLM to generate sustainable irrigation and fertilization recommendations</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an AI agricultural assistant specializing in sustainable precision farming."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the following data, provide sustainable irrigation and fertilization recommendations: <span class="hljs-subst">{data_summary}</span>"</span>}
    ]
)

recommendations = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(recommendations)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725979473815/a41d0a56-1329-4595-adb6-d5fe859faf1b.png" alt="a41d0a56-1329-4595-adb6-d5fe859faf1b" class="image--center mx-auto" width="2048" height="1898" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Sustainable Irrigation <span class="hljs-keyword">and</span> Fertilization Recommendations:**

- **Zone A Irrigation:** Since soil moisture <span class="hljs-keyword">is</span> at <span class="hljs-number">45</span>%, no immediate irrigation <span class="hljs-keyword">is</span> needed. Reassess after the next rainfall. Depending on the forecasted <span class="hljs-number">15</span>mm rain, irrigation may <span class="hljs-keyword">not</span> be necessary <span class="hljs-keyword">for</span> at least <span class="hljs-number">5</span> days.

- **Zone B Irrigation:** Soil moisture <span class="hljs-keyword">in</span> Zone B <span class="hljs-keyword">is</span> at <span class="hljs-number">30</span>%, which <span class="hljs-keyword">is</span> approaching a critical threshold. Schedule light irrigation (<span class="hljs-number">20</span>mm) <span class="hljs-keyword">for</span> Zone B tomorrow to maintain optimal soil moisture, then reassess after the next week<span class="hljs-string">'s rain.

- **Fertilization Strategy:** The vegetation health index of 0.85 indicates good crop health. Continue applying fertilizer at 60% of the standard rate, focused only in areas of Zone B where soil nutrient data indicates low nitrogen. This approach will reduce overuse of fertilizers and protect the soil from degradation.</span>
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725979520747/359bc197-b573-400c-9a8f-967fc57f2c20.png" alt="359bc197-b573-400c-9a8f-967fc57f2c20" class="image--center mx-auto" width="2048" height="894" loading="lazy"></a></p>
<h4 id="heading-example-2-ai-powered-farm-management-software-for-crop-monitoring-and-anomaly-detection"><strong>Example 2: AI-powered farm management software for crop monitoring and anomaly detection</strong></h4>
<p><strong>Objective:</strong> Integrate an LLM with AI-powered farm management software that uses computer vision and predictive analytics to identify crop anomalies like nutrient deficiencies or pest infestations and provide sustainable intervention strategies.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample data from farm management software using computer vision for anomaly detection</span>
crop_data = {
    <span class="hljs-string">"drone_images"</span>: {
        <span class="hljs-string">"zones"</span>: {
            <span class="hljs-string">"zone_1"</span>: {<span class="hljs-string">"anomaly_detected"</span>: <span class="hljs-string">"nitrogen deficiency"</span>, <span class="hljs-string">"severity"</span>: <span class="hljs-string">"moderate"</span>},
            <span class="hljs-string">"zone_2"</span>: {<span class="hljs-string">"anomaly_detected"</span>: <span class="hljs-string">"early-stage pest infestation"</span>, <span class="hljs-string">"severity"</span>: <span class="hljs-string">"low"</span>}
        }
    },
    <span class="hljs-string">"crop_health"</span>: {
        <span class="hljs-string">"growth_stage"</span>: <span class="hljs-string">"mid-vegetative"</span>,
        <span class="hljs-string">"projected_yield"</span>: <span class="hljs-number">4000</span>  <span class="hljs-comment"># kg/ha</span>
    }
}

<span class="hljs-comment"># Describe data for LLM input</span>
crop_data_summary = (
    <span class="hljs-string">f"Drone images have detected a nitrogen deficiency in Zone 1, with moderate severity, and an early-stage pest infestation in Zone 2, with low severity. "</span>
    <span class="hljs-string">f"The crops are in the mid-vegetative growth stage, and the projected yield is currently 4000 kg/ha."</span>
)

<span class="hljs-comment"># Use LLM to generate sustainable recommendations for addressing detected anomalies</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an AI expert specializing in sustainable crop monitoring and intervention strategies."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the detected anomalies and current crop health, provide sustainable intervention strategies: <span class="hljs-subst">{crop_data_summary}</span>"</span>}
    ]
)

sustainable_strategy = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(sustainable_strategy)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725979561817/61cfc3d9-0735-4192-9a30-2602da14319a.png" alt="A screenshot of Python code showing the use of OpenAI to analyze farm management data and generate sustainable recommendations based on detected anomalies in crop health. The code includes sample crop data with information on anomalies detected via drone images, summarized crop data for input into a large language model (LLM), and the generation of a response using the LLM to provide sustainable intervention strategies." class="image--center mx-auto" width="2048" height="1682" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Sustainable Intervention Strategies:**

- **Zone <span class="hljs-number">1</span> Nitrogen Deficiency:** Apply a nitrogen-rich organic fertilizer such <span class="hljs-keyword">as</span> composted manure to address the deficiency <span class="hljs-keyword">in</span> a sustainable manner. Spread the fertilizer evenly across the affected area, ensuring a slow-release approach to prevent nitrogen runoff <span class="hljs-keyword">and</span> soil contamination.

- **Zone <span class="hljs-number">2</span> Pest Infestation:** Given the early stage <span class="hljs-keyword">and</span> low severity of the pest infestation, implement biological pest control methods such <span class="hljs-keyword">as</span> introducing natural predators <span class="hljs-keyword">or</span> using neem oil to minimize chemical pesticide use. Continue monitoring the affected area closely <span class="hljs-keyword">for</span> any escalation <span class="hljs-keyword">in</span> pest activity.

- **General Management:** Maintain regular soil testing <span class="hljs-keyword">and</span> drone-based monitoring to ensure nutrient levels are balanced <span class="hljs-keyword">and</span> pest control measures are effective. This proactive approach will protect <span class="hljs-keyword">yield</span> potential <span class="hljs-keyword">while</span> minimizing environmental impact.
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725979636599/4a5e3a68-c347-4b7d-afa6-13e167a15436.png" alt="Sustainable Intervention Strategies.  Three main points are mentioned: 1. Zone 1 Nitrogen Deficiency: Application of organic fertilizer to address the deficiency sustainably.2. Zone 2 Pest Infestation: Use of biological pest control methods and regular monitoring.3. General Management: Regular soil testing and drone-based monitoring for nutrient balance and effective pest control, minimizing environmental impact. - lunartech.ai" class="image--center mx-auto" width="2048" height="864" loading="lazy"></a></p>
<h4 id="heading-example-3-ai-enhanced-predictive-analytics-for-climate-adaptive-sustainable-farming"><strong>Example 3: AI-enhanced predictive analytics for climate-adaptive sustainable farming</strong></h4>
<p><strong>Objective:</strong> Use LLM to analyze predictive climate data and provide sustainable, climate-adaptive strategies for planting, crop selection, and soil management. The goal is to optimize land use in light of changing weather patterns and minimize environmental risks.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> openai

<span class="hljs-comment"># Sample predictive climate data and historical trends</span>
climate_data = {
    <span class="hljs-string">"historical_weather"</span>: {
        <span class="hljs-string">"average_temp_summer"</span>: <span class="hljs-number">32</span>,  <span class="hljs-comment"># °C</span>
        <span class="hljs-string">"average_rainfall_summer"</span>: <span class="hljs-number">80</span>  <span class="hljs-comment"># mm/month</span>
    },
    <span class="hljs-string">"predictive_weather_model"</span>: {
        <span class="hljs-string">"next_summer"</span>: {<span class="hljs-string">"projected_temp"</span>: <span class="hljs-number">35</span>, <span class="hljs-string">"projected_rainfall"</span>: <span class="hljs-number">50</span>},  <span class="hljs-comment"># °C, mm</span>
        <span class="hljs-string">"risk_assessment"</span>: {<span class="hljs-string">"drought_risk"</span>: <span class="hljs-string">"high"</span>, <span class="hljs-string">"heatwave_risk"</span>: <span class="hljs-string">"moderate"</span>}
    },
    <span class="hljs-string">"soil_data"</span>: {
        <span class="hljs-string">"organic_matter"</span>: <span class="hljs-number">2.5</span>,  <span class="hljs-comment"># percentage</span>
        <span class="hljs-string">"soil_type"</span>: <span class="hljs-string">"loamy"</span>,
        <span class="hljs-string">"moisture_retention"</span>: <span class="hljs-string">"moderate"</span>
    }
}

<span class="hljs-comment"># Describe data for LLM input</span>
climate_data_summary = (
    <span class="hljs-string">f"Historically, the average summer temperature has been 32°C with 80mm of rainfall per month. "</span>
    <span class="hljs-string">f"However, next summer's predictive model suggests temperatures may rise to 35°C with reduced rainfall of 50mm. "</span>
    <span class="hljs-string">f"There is a high risk of drought and a moderate risk of heatwaves. The soil is loamy with 2.5% organic matter and moderate moisture retention."</span>
)

<span class="hljs-comment"># Use LLM to generate climate-adaptive, sustainable land use strategies</span>
response = openai.ChatCompletion.create(
    model=<span class="hljs-string">"gpt-4"</span>,
    messages=[
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"system"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">"You are an AI expert in sustainable land use and climate-adaptive farming."</span>},
        {<span class="hljs-string">"role"</span>: <span class="hljs-string">"user"</span>, <span class="hljs-string">"content"</span>: <span class="hljs-string">f"Based on the predictive climate and soil data, provide sustainable, climate-adaptive farming strategies: <span class="hljs-subst">{climate_data_summary}</span>"</span>}
    ]
)

climate_adaptive_strategy = response.choices[<span class="hljs-number">0</span>].message[<span class="hljs-string">'content'</span>]
print(climate_adaptive_strategy)
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725979718688/31c361cf-a662-408c-a803-f15c0febfd45.png" alt="Screenshot of Python code creating a predictive climate model using the OpenAI API. The code defines historical weather data, a predictive weather model, and soil data. It also summarizes the climate data and uses a language model to generate climate-adaptive farming strategies based on the provided data. The final line prints the generated farming strategy." class="image--center mx-auto" width="2048" height="1868" loading="lazy"></a></p>
<p><strong>Sample Output:</strong></p>
<pre><code class="lang-python">**Climate-Adaptive Sustainable Farming Strategies:**

- **Crop Selection:** Choose drought-resistant crop varieties such <span class="hljs-keyword">as</span> sorghum, millet, <span class="hljs-keyword">or</span> certain legumes that are well-suited to withstand higher temperatures <span class="hljs-keyword">and</span> lower rainfall. Consider crop rotation that improves soil health <span class="hljs-keyword">and</span> enhances water retention.

- **Soil Management:** Improve soil organic matter content by incorporating cover crops <span class="hljs-keyword">or</span> applying organic compost. This will enhance soil moisture retention <span class="hljs-keyword">and</span> provide a buffer against heatwaves <span class="hljs-keyword">and</span> drought conditions. Mulching <span class="hljs-keyword">is</span> also recommended to conserve soil moisture <span class="hljs-keyword">and</span> reduce evaporation.

- **Irrigation Strategy:** Given the high risk of drought, implement drip irrigation systems to deliver water directly to the plant roots, maximizing water efficiency. Utilize AI-powered precision irrigation tools to monitor real-time soil moisture <span class="hljs-keyword">and</span> minimize water waste.

- **Heatwave Mitigation:** Use shade cloth <span class="hljs-keyword">or</span> other protective structures during the peak heat periods to shield sensitive crops <span class="hljs-keyword">from</span> excessive heat stress. Additionally, schedule irrigation during early morning <span class="hljs-keyword">or</span> late evening to reduce water loss due to evaporation.
</code></pre>
<p><a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1725979767234/e39dca21-62cc-4a17-9954-b0b5ebbddf77.png" alt="A screenshot displaying text on Climate-Adaptive Sustainable Farming Strategies. It includes points on crop selection, soil management, irrigation strategy, and heatwave mitigation. The text emphasizes choosing drought-resistant crops, using organic compost, implementing drip irrigation, and using protective structures for heat stress." class="image--center mx-auto" width="2048" height="974" loading="lazy"></a></p>
<p><strong>In Example 1</strong>, we used LLMs to analyze data from sensors, satellite imagery, and weather forecasts to optimize irrigation and fertilizer use, focusing on sustainable land use and conservation of resources.</p>
<p><strong>In Example 2</strong>, LLMs helped detect crop anomalies (such as nutrient deficiencies and pest infestations) through computer vision, providing sustainable, targeted interventions that minimize chemical use and prevent further damage.</p>
<p><strong>And in Example 3</strong>, LLMs helped us analyze predictive climate models and soil data to offer sustainable land use strategies, advising farmers on adaptive practices that mitigate the risks of drought and heatwaves, promote soil health, and optimize resource use.</p>
<p>In these examples, LLMs enhanced decision-making in agriculture by processing complex data and providing actionable, sustainable strategies that increased productivity while reducing environmental impact. These AI-enhanced systems promote the long-term sustainability of agricultural practices.</p>
<p>The integration of AI technologies in sustainable land use strategies holds transformative potential for the agricultural sector. Precision agriculture, AI-powered farm management software, and sustainable farming practices driven by AI collectively optimize resource management, enhance crop yield, and minimize environmental impact.</p>
<p>Financial incentives further support the adoption of these technologies, making sustainable farming practices accessible to a broader range of farmers.</p>
<p>As we embrace the future of agriculture with AI, we move towards a more efficient, productive, and environmentally conscious approach to farming. By leveraging data-driven insights and innovative solutions, farmers can contribute to building a resilient and sustainable food system that meets the needs of a growing global population. The journey towards sustainable agriculture is not without challenges, but with AI as a powerful ally, we are well-equipped to navigate these challenges and shape a prosperous future for farming.</p>
<h2 id="heading-chapter-8-efficient-water-use-and-irrigation-systems-with-ai-guidance">Chapter 8: Efficient Water Use and Irrigation Systems with AI Guidance</h2>
<p>Efficient water management is a critical element in effective farming practices. And it’s one where AI's intervention can make a profound difference.</p>
<p>As climate change intensifies water scarcity, innovative solutions become more necessary. AI-guided irrigation systems stand out as revolutionary tools that promise not only to optimize water usage but also to potentially transform agricultural practices.</p>
<p>This chapter delves into how AI-based irrigation systems are forging a new path in sustainable agriculture, providing the depth and nuance necessary for a scholarly exploration.</p>
<h3 id="heading-precision-irrigation-techniques-tailoring-watering-strategies"><strong>Precision Irrigation Techniques: Tailoring Watering Strategies</strong></h3>
<p>AI-powered precision irrigation is changing how water resources are managed. Traditional irrigation methods often involve a one-size-fits-all approach, causing either excessive or insufficient watering. But AI algorithms can tailor water distribution by analyzing a wealth of data, including soil moisture levels, weather conditions, and plant health. For instance, a vineyard might use AI to monitor soil moisture across different zones, ensuring each vine receives the optimal amount of water without wastage.</p>
<p>These AI systems gather real-time data from sensors embedded in the soil and parse this information to determine precise watering needs, ensuring that crops receive just the right amount of moisture when they need it. This intelligent approach reduces water waste significantly and enhances crop yield.</p>
<p>Imagine an arid region where water scarcity is a daily challenge. AI-guided systems can stretch each drop of water to its fullest potential, safeguarding both the crops and the environment.</p>
<h3 id="heading-automated-irrigation-scheduling-dynamic-and-responsive-systems"><strong>Automated Irrigation Scheduling: Dynamic and Responsive Systems</strong></h3>
<p>Predictive analytics and weather forecasting are pivotal in AI-driven automated irrigation scheduling. Traditional methods often fail to account for unpredictable weather variations, leading to inefficiencies. AI systems transform this by autonomously adjusting irrigation schedules in response to real-time environmental inputs.</p>
<p>For example, predictive models can anticipate a week of heavy rainfall. The AI system preemptively adjusts irrigation schedules, avoiding unnecessary watering and conserving water for drier times. This adaptability is essential for regions experiencing erratic weather patterns due to climate change.</p>
<p>Farmers benefit immensely, as they can ensure water resources are used efficiently without the constant need to manually adjust schedules, leading to better crop management and resource use efficiency.</p>
<h3 id="heading-soil-moisture-monitoring-foundation-of-data-driven-decisions"><strong>Soil Moisture Monitoring: Foundation of Data-Driven Decisions</strong></h3>
<p>Soil moisture monitoring using AI represents the synthesis of technology and agronomy. By utilizing advanced sensors and computer vision technologies, AI systems provide high-fidelity soil moisture data, crucial for informed irrigation decisions. In practical terms, a farmer overseeing vast fields can install soil moisture sensors at various depths and locations. The AI system continuously aggregates this data, presenting actionable insights to the farmer about when and where to irrigate.</p>
<p>Consider the delicate balance required in cultivating crops such as tomatoes that are sensitive to both drought stress and water logging. Continuous soil moisture monitoring aids in maintaining this balance, ensuring that water is neither overused nor insufficiently applied.</p>
<p>These systems provide peace of mind, enabling farmers to focus on other critical agricultural tasks, knowing that their irrigation needs are being managed with precision.</p>
<h3 id="heading-smart-water-delivery-systems-customizing-for-optimal-efficiency"><strong>Smart Water Delivery Systems: Customizing for Optimal Efficiency</strong></h3>
<p>AI algorithms can fine-tune the delivery of water, considering variables like soil type, crop requirements, and field topography. This approach transforms generic irrigation practices into targeted strategies tailored to specific agricultural ecosystems.</p>
<p>Let’s take an example of a diverse farm with sections of sandy and clay-based soils. AI systems analyze these soil conditions and create bespoke irrigation plans for each section, ensuring optimal water absorption and minimal run-off.</p>
<p>This precision maximizes water use efficiency, improving crop yields and conserving water resources. The benefits extend beyond just individual farms—such practices can lead to regional water conservation efforts, potentially alleviating local water scarcity issues. The ability to customize irrigation strategies means that farmers can cultivate a wider variety of crops, confident that their water needs will be met efficiently.</p>
<h3 id="heading-enhancing-crop-yields-the-ripple-effect-of-efficient-water-use"><strong>Enhancing Crop Yields: The Ripple Effect of Efficient Water Use</strong></h3>
<p>Efficient water management is not solely about conserving water—it's intrinsically linked to crop productivity. AI-guided irrigation systems, with their precision and accuracy, ensure that crops receive consistent, optimal hydration. This leads to healthier plants, better growth, and ultimately, higher yields. For instance, a study on cotton farming demonstrated that precision irrigation using AI improved yield by 25% compared to traditional practices.</p>
<p>Implementing such systems on a global scale can revolutionize agricultural productivity. In regions where water scarcity and food insecurity are interlinked, AI-driven irrigation can break this cycle, providing reliable water supply to crops and thereby boosting food production. This has far-reaching implications for global food security, highlighting the critical role of AI in addressing complex agricultural challenges.</p>
<h3 id="heading-sustainable-practices-bridging-technology-and-environmental-stewardship"><strong>Sustainable Practices: Bridging Technology and Environmental Stewardship</strong></h3>
<p>Oil extraction, industrial activities, and misuse have led to the diminishing reserves of freshwater globally. AI in irrigation promotes sustainability by reducing unnecessary water usage and preserving natural resources. For example, the use of AI in Israel's arid regions helps farmers optimize the scarce water supplies, demonstrating that technology can be an ally in environmental stewardship.</p>
<p>These AI systems contribute to sustainable agricultural practices, balancing the needs of present and future generations. Farmers are not just incentivized to conserve water but also to adopt practices that reduce soil degradation and promote biodiversity. The integration of AI technologies in farming becomes a model for other industries, showcasing how advanced technology can aid in achieving environmental goals.</p>
<h3 id="heading-overcoming-challenges-addressing-implementation-barriers"><strong>Overcoming Challenges: Addressing Implementation Barriers</strong></h3>
<p>Despite the numerous advantages, the integration of AI-guided irrigation systems isn't devoid of challenges. High initial costs and the need for technical expertise can be significant barriers for smallholder farmers. Addressing these challenges requires a multipronged approach involving policy incentives, financing options, and educational programs.</p>
<p>For instance, government subsidies and low-interest loans can make AI technologies more accessible. Collaborative efforts between agritech firms and agricultural extensions can also play a vital role in educating farmers about the operational and financial benefits of these systems. Creating a support ecosystem is essential for widespread adoption, ensuring that no farmer is left behind in the transition towards smarter irrigation practices.</p>
<h3 id="heading-future-prospects-evolving-technologies-and-expanding-horizons"><strong>Future Prospects: Evolving Technologies and Expanding Horizons</strong></h3>
<p>As technology evolves, so do the possibilities for AI in irrigation management. Future developments may include enhanced machine learning models that can predict long-term trends and AI systems that integrate seamlessly with other smart farming technologies, such as autonomous tractors and drones. Imagine an ecosystem where various AI technologies interact, creating a self-regulating agricultural environment.</p>
<p>Continuous advancements will expand the scope of AI applications, making them more robust and scalable. The potential to integrate AI with renewable energy sources, like solar-powered irrigation systems, can further enhance sustainability efforts. The horizon is vast, and as AI technology matures, its impact on agriculture can only increase.</p>
<p>The future of agriculture is intertwined with advancements in AI technology. As we prepare for this future, understanding the current capabilities and potential of AI-guided irrigation systems is imperative. This knowledge equips stakeholders with the insights needed to leverage these technologies for maximum benefit.</p>
<h4 id="heading-the-path-forward"><strong>The Path Forward</strong></h4>
<p>AI-guided irrigation systems exemplify how technology can revolutionize water management in agriculture, offering solutions that are both sustainable and efficient. By leveraging data, real-time analysis, and predictive models, these systems optimize water usage and enhance crop yields, addressing pressing issues like water scarcity and food security. Embracing these technologies requires overcoming certain barriers, but the potential benefits make the effort worthwhile.</p>
<p>As you move forward, consider how the integration of AI in your irrigation practices can align with broader goals of sustainability and increased productivity. Encourage a proactive approach—explore financing options, seek educational resources, and engage with technology providers. The path forward is paved with opportunities, and the fusion of AI and agriculture is a promising frontier, ready to redefine the future of farming.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The integration of AI in agriculture presents an exciting opportunity to revolutionize farming practices and significantly boost crop yields. The potential of AI-enhanced farming to increase productivity by 70% by 2030 is a game-changer for the agriculture industry.</p>
<p>By leveraging AI technologies such as machine learning and predictive analytics, farmers can make more informed decisions and optimize resource utilization to achieve higher yields. Investing in AI solutions for agriculture is not just an option but a necessity for staying competitive in the rapidly evolving field.</p>
<p>Embracing this technology can lead to sustainable practices, reduced waste, and increased profitability for farmers worldwide. As we look towards the future of farming, it is clear that AI will play a crucial role in ensuring food security and meeting</p>
<h2 id="heading-faq">FAQ</h2>
<h3 id="heading-what-is-ai-in-agriculture">What is AI in agriculture?</h3>
<p>AI in agriculture refers to the use of artificial intelligence technology and techniques in the farming and agricultural industry. This can include AI-powered tools and systems that help farmers optimize crop growth, monitor weather patterns, and make data-driven decisions for increased efficiency and productivity.</p>
<h3 id="heading-will-ai-replace-human-labor-in-agriculture">Will AI replace human labor in agriculture?</h3>
<p>AI in agriculture is not meant to replace human labor, but rather enhance it. AI technology can provide valuable insights and recommendations to help farmers make more informed decisions and increase crop yields. With the use of AI, farmers can save time and resources while also increasing their productivity.</p>
<h3 id="heading-what-are-the-potential-benefits-of-using-ai-in-agriculture">What are the potential benefits of using AI in agriculture?</h3>
<p>Some potential benefits of using AI in agriculture include increased crop yields, reduced costs, improved efficiency, and better decision-making.</p>
<p>With AI technology, farmers can analyze data and make informed decisions about planting, harvesting, and managing crops. It can also help with predicting weather patterns, optimizing irrigation schedules, and identifying diseases and pests early on.</p>
<h3 id="heading-how-does-ai-help-in-increasing-crop-yields">How does AI help in increasing crop yields?</h3>
<p>AI in agriculture can help increase crop yields by using advanced technologies such as machine learning and data analytics to optimize farming practices. This can include predicting optimal planting and harvesting times, identifying potential pest or disease outbreaks, and optimizing irrigation and fertilizer use. By using AI, farmers can make more informed decisions and improve efficiency, leading to higher crop yields.</p>
<h3 id="heading-how-does-ai-help-with-sustainable-agriculture">How does AI help with sustainable agriculture?</h3>
<p>AI can help with sustainable agriculture in several ways, such as: Predicting weather patterns and optimizing irrigation schedules to reduce water waste. Analyzing soil data and recommending the best crops and fertilizers to maximize yield and minimize environmental impact. Monitoring crop health and detecting pests and diseases early on, allowing for targeted treatment and reducing the need for harmful pesticides. Optimizing planting and harvesting schedules for maximum efficiency and reducing labor and fuel costs.</p>
<h3 id="heading-what-are-some-examples-of-ai-technology-used-in-farming">What are some examples of AI technology used in farming?</h3>
<p>Some examples of AI technology used in farming include:</p>
<ul>
<li><p>Automated tractors and harvesters that use computer vision and machine learning algorithms to optimize planting and harvesting processes.</p>
</li>
<li><p>Soil sensors and drones that collect data on soil moisture, nutrient levels, and crop health, allowing farmers to make data-driven decisions.</p>
</li>
<li><p>Predictive analytics software that uses AI to analyze weather patterns and predict crop yields, helping farmers plan more effectively.</p>
</li>
<li><p>Robotic weeders and pest control systems that use AI to identify and target specific plants or pests, reducing the use of harmful chemicals.</p>
</li>
</ul>
<h3 id="heading-how-can-you-dive-deeper"><strong>How Can You Dive Deeper?</strong></h3>
<p>After studying this guide, if you're keen to dive even deeper and structured learning is your style, consider joining us at <a target="_blank" href="https://lunartech.ai/">LunarTech</a>. We offer an <a target="_blank" href="https://www.lunartech.ai/bootcamp/ai-engineering-bootcamp"><strong>AI Engineering Bootcamp</strong></a><strong>,</strong> <a target="_blank" href="https://academy.lunartech.ai/"><strong>77+ individual courses</strong></a><strong>,</strong> and a <strong>Bootcamp in Data Science, Machine Learning, and AI.</strong></p>
<p>You can check out our <a target="_blank" href="https://www.lunartech.ai/bootcamp/data-science-bootcamp">Ultimate Data Science Bootcamp</a> and join <a target="_blank" href="https://lunartech.ai/pricing/">a free trial</a> to try the content first hand. This has earned the recognition of being one of the Best Data Science Bootcamps of 2023, and has been featured in esteemed publications like <a target="_blank" href="https://www.forbes.com.au/brand-voice/uncategorized/not-just-for-tech-giants-heres-how-lunartech-revolutionizes-data-science-and-ai-learning/">Forbes</a>, <a target="_blank" href="https://finance.yahoo.com/news/lunartech-launches-game-changing-data-115200373.html">Yahoo</a>, <a target="_blank" href="https://www.entrepreneur.com/ka/business-news/outpacing-competition-how-lunartech-is-redefining-the/463038">Entrepreneur</a> and more. This is your chance to be a part of a community that thrives on innovation and knowledge. Here is the Welcome message:</p>
<h3 id="heading-transform-your-future-with-data-science-amp-ai"><strong>Transform Your Future with Data Science &amp; AI</strong></h3>
<p>Ready to break into the booming field of Data Science and AI? Download our free eBook, Six-Figure Data Science Bootcamp, and discover the exact steps to build in-demand skills, gain real-world experience, and land your dream job.</p>
<p>🎯 <strong>What You’ll Learn:</strong><br>✔️ Master essential skills top employers crave.<br>✔️ Build a portfolio, even as a beginner.<br>✔️ Ace interviews and negotiate a top-tier salary.<br>✔️ Explore industries actively hiring Data Scientists and AI specialists.</p>
<p>👉 <a target="_blank" href="https://join.lunartech.ai/artificial-intelligence-in-agriculture">Download the Free eBook</a></p>
<h3 id="heading-connect-with-me"><strong>Connect with Me</strong></h3>
<ul>
<li><p><a target="_blank" href="https://ca.linkedin.com/in/vahe-aslanyan">Follow me on LinkedIn for a ton of Free Resources in CS, ML and AI</a></p>
</li>
<li><p><a target="_blank" href="https://vaheaslanyan.com/">Visit my Personal Website</a></p>
</li>
<li><p>Subscribe to my <a target="_blank" href="https://tatevaslanyan.substack.com/">The Data Science and AI Newsletter</a></p>
</li>
</ul>
<p>If you want to learn more about a career in Data Science, Machine Learning and AI, and learn how to secure a Data Science job, you can download this free <a target="_blank" href="https://downloads.tatevaslanyan.com/six-figure-data-science-ebook">Data Science and AI Career Handbook</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Microservices Book – Learn How to Build and Manage Services in the Cloud ]]>
                </title>
                <description>
                    <![CDATA[ In today’s fast-paced tech landscape, microservices have emerged as one of the most efficient ways to architect and manage scalable, flexible, and resilient cloud-based systems. Whether you're working with large-scale applications or building somethi... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/the-microservices-book-build-and-manage-services-in-the-cloud/</link>
                <guid isPermaLink="false">67488780f60a357b6cecd459</guid>
                
                    <category>
                        <![CDATA[ Microservices ]]>
                    </category>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Adekola Olawale ]]>
                </dc:creator>
                <pubDate>Thu, 28 Nov 2024 15:08:48 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1732028836710/aedce669-1e41-4bb1-8619-6994ed741b5c.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In today’s fast-paced tech landscape, microservices have emerged as one of the most efficient ways to architect and manage scalable, flexible, and resilient cloud-based systems.</p>
<p>Whether you're working with large-scale applications or building something new from scratch, understanding microservices architecture is crucial to developing software that meets modern business needs.</p>
<p>This book is designed to provide you with a comprehensive understanding of microservices, from building robust services to managing them effectively in the cloud.</p>
<h3 id="heading-what-will-you-learn">What Will You Learn?</h3>
<p>Throughout this book, we’ll walk you through the <strong>fundamental principles of microservices architecture</strong>, focusing on:</p>
<ul>
<li><p><strong>Designing and building microservices</strong>: We’ll cover how to structure services, choose the right technology stack, define clear APIs and contracts, and utilize essential design patterns.</p>
</li>
<li><p><strong>Managing microservices in the cloud</strong>: You'll learn about cloud platforms like AWS, Azure, and Google Cloud, as well as containerization with Docker and orchestration using Kubernetes.</p>
</li>
<li><p><strong>Testing, deployment, and scaling strategies</strong>: We’ll dive into how to test microservices effectively, set up continuous integration/continuous deployment (CI/CD) pipelines, and use automation to deploy and scale your services.</p>
</li>
<li><p><strong>Security, monitoring, and troubleshooting</strong>: We’ll discuss security considerations and real-time monitoring solutions for microservices in-depth, so you can keep your system resilient and secure.</p>
</li>
<li><p><strong>Case studies and real-world examples</strong>: We'll explore how companies like Netflix, Amazon, and Uber use microservices to handle millions of requests daily and how you can apply these concepts to your projects.</p>
</li>
<li><p><strong>Common pitfalls and solutions</strong>: Finally, you’ll learn about the common challenges that arise when implementing microservices and how to address them.</p>
</li>
</ul>
<p>By the end of this book, you’ll have a solid understanding of the <strong>best practices for building and managing microservices</strong>, with the confidence to deploy and scale these architectures in a cloud environment.</p>
<h3 id="heading-prerequisites">Prerequisites</h3>
<p>To get the most out of this guide, I recommend that you have:</p>
<ol>
<li><p><strong>Basic knowledge of programming</strong>: While we’ll use <strong>JavaScript/Node.js</strong> for many examples, prior experience with any backend programming language will help you follow along.</p>
</li>
<li><p><strong>Familiarity with REST APIs</strong>: Since microservices often communicate over HTTP, understanding how REST APIs work will be beneficial.</p>
</li>
<li><p><strong>A basic understanding of cloud services</strong>: Experience with cloud platforms (AWS, Azure, Google Cloud) will help as we dive into cloud-native services.</p>
</li>
<li><p><strong>Installed Tools</strong>:</p>
<ul>
<li><p><strong>Docker</strong>: We’ll use Docker for creating and managing containers.</p>
</li>
<li><p><strong>Node.js</strong>: If you’re following along with the JavaScript examples, make sure you have Node.js installed on your machine.</p>
</li>
<li><p><strong>Postman</strong>: For testing APIs, Postman will be useful.</p>
</li>
<li><p><strong>Git</strong>: Version control knowledge and Git installed on your machine to work with repositories.</p>
</li>
<li><p><strong>A cloud provider account</strong> (for example, AWS, Azure, or Google Cloud) to deploy your microservices into the cloud.</p>
</li>
<li><p><strong>Kubernetes (Optional)</strong>: If you’d like to experiment with orchestration locally.</p>
</li>
<li><p><strong>A code editor</strong> (like Visual Studio Code) to write and manage your code.</p>
</li>
<li><p><strong>Cloud CLI tools</strong> (for example AWS CLI, Google Cloud SDK): These will be essential for deploying and managing microservices in your cloud provider.</p>
</li>
</ul>
</li>
</ol>
<p>This book is structured to guide you from the basics to advanced concepts, with practical examples, step-by-step tutorials, and real-world scenarios that will prepare you for building modern microservices in a cloud environment.</p>
<p>Whether you’re a developer looking to improve your microservices skills or an architect designing complex cloud-native systems, this book will equip you with the knowledge to succeed.</p>
<p>Let’s begin the journey toward mastering microservices and cloud management!</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><p><a class="post-section-overview" href="#heading-what-are-microservices">What are Microservices?</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-what-is-a-microservices-architecture">What is a Microservices Architecture?</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-key-characteristics-of-microservices">Key Characteristics of Microservices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-benefits-of-microservices">Benefits of Microservices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-challenges-of-microservices">Challenges of Microservices</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-microservices-vs-monolithic-architecture">Microservices vs Monolithic Architecture</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-core-microservices-components-and-concepts">Core Microservices Concepts and Components</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-microservices-design-principles">Microservices Design Principles</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-service-communication-synchronous-vs-asynchronous">Service Communication: Synchronous vs Asynchronous</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-restful-apis">RESTful APIs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-grpc-and-protocol-buffers">gRPC and Protocol Buffers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-message-brokers-like-rabbitmq-and-kafka">Message Brokers (like RabbitMQ and Kafka)</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-data-management-in-microservices">Data Management in Microservices</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-database-per-service-pattern">Database per Service Pattern</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-data-consistency-and-synchronization">Data Consistency and Synchronization</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-service-discovery-and-load-balancing">Service Discovery and Load Balancing</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-build-and-design-microservices">How to Build and Design Microservices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-implement-microservices">How to Implement Microservices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-test-microservices">How to Test Microservices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-deploy-microservices">How to Deploy Microservices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-how-to-manage-microservices-in-the-cloud">How to Manage Microservices in the Cloud</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-cloud-platforms-and-services">Cloud Platforms and Services</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-containerization-and-orchestration">Containerization and Orchestration</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-introduction-to-containers-docker">Introduction to Containers (Docker)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-container-orchestration-tools-kubernetes-docker-swarm">Container Orchestration Tools (Kubernetes, Docker Swarm)</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-helm-charts-and-kubernetes-operators">Helm Charts and Kubernetes Operators</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-continuous-integration-and-continuous-deployment-cicd-1">Continuous Integration and Continuous Deployment (CI/CD)</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-cicd-pipelines-and-best-practices">CI/CD Pipelines and Best Practices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-tools-and-platforms-for-cicd">Tools and Platforms for CI/CD</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-automated-testing-and-deployment-strategies">Automated Testing and Deployment Strategies</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-monitoring-and-logging">Monitoring and Logging</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-security-considerations-1">Security Considerations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-case-studies-and-real-world-examples">Case Studies and Real-World Examples</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-case-study-1-e-commerce-platform">Case Study 1: E-Commerce Platform</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-case-study-2-streaming-media-service">Case Study 2: Streaming Media Service</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-case-study-3-financial-services-application">Case Study 3: Financial Services Application</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-real-world-examples-of-microservices">Real-World Examples of Microservices</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-1-netflix-scaling-content-and-recommendations">1. Netflix: Scaling Content and Recommendations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-2-amazon-managing-orders-and-products-at-scale">2. Amazon: Managing Orders and Products at Scale</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-3-uber-managing-rides-drivers-and-payments">3. Uber: Managing Rides, Drivers, and Payments</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-benefits-of-using-microservices-in-these-companies">Benefits of Using Microservices in These Companies</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-common-pitfalls-and-how-to-avoid-them-in-microservices">Common Pitfalls and How to Avoid Them in Microservices</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-strategies-to-address-and-avoid-common-issues">Strategies to Address and Avoid Common Issues</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-future-trends-and-innovations">Future Trends and Innovations</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ol>
<h2 id="heading-what-are-microservices">What are Microservices?</h2>
<p>This section introduces microservices architecture by exploring its foundational principles and distinguishing it from traditional monolithic approaches. It covers the defining features of microservices—like scalability, independent deployment, and support for diverse technologies—that make it a preferred architecture for modern applications.</p>
<p>You’ll also gain insights into the advantages of microservices, such as enhanced fault isolation and flexibility, as well as the challenges, including increased complexity in managing inter-service communication, maintaining data consistency, and ensuring security.</p>
<p>By understanding the key trade-offs involved, you’ll develop a comprehensive view of microservices and their role in contemporary application development. This foundation should equip you, as a developer and architect, with the necessary perspective to assess whether microservices are the right fit for your projects.</p>
<p>Microservices, or the microservices architecture, is a modern approach to designing software systems.</p>
<p>Unlike traditional monolithic applications, which are built as a single, unified unit, a microservices-based application is divided into a set of smaller, independent services.</p>
<p>Each service in a microservices architecture is responsible for a specific function—such as user authentication, payment processing, or data storage—and is designed to be independently deployable and scalable.</p>
<p>These services communicate with each other over a network, typically using lightweight protocols like HTTP or messaging queues, enabling them to operate as separate entities while contributing to the functionality of the larger system.</p>
<p>The primary advantage of microservices lies in their independence. Each service can be built, deployed, and managed independently, allowing development teams to work on different parts of the system simultaneously.</p>
<p>This setup promotes flexibility, speed in development and deployment, and the ability to scale each service according to specific demands without affecting others. Microservices are particularly well-suited for cloud environments, where resources can be allocated dynamically based on real-time needs.</p>
<h3 id="heading-what-is-a-microservices-architecture">What is a Microservices Architecture?</h3>
<p>Microservices architecture is an approach to designing and developing software applications where a single application is composed of multiple loosely coupled, independently deployable services.</p>
<p>Each service corresponds to a specific business functionality and operates as an independent unit that communicates with other services through well-defined APIs.</p>
<h4 id="heading-key-points-about-microservices">Key Points about Microservices</h4>
<ul>
<li><p><strong>Modular Design:</strong> Microservices break down an application into small, self-contained modules, each responsible for a distinct piece of functionality.<br>  This modular approach promotes better organization and separation of concerns.</p>
</li>
<li><p><strong>Independence:</strong> Each microservice can be developed, deployed, and scaled independently. This independence allows for more flexible and agile development practices.</p>
</li>
<li><p><strong>Autonomy:</strong> Microservices operate independently and are loosely coupled, meaning that changes in one service do not necessarily impact others. This autonomy enhances fault tolerance and resilience.</p>
</li>
</ul>
<h3 id="heading-key-characteristics-of-microservices">Key Characteristics of Microservices</h3>
<ol>
<li><h4 id="heading-decentralized-data-management">Decentralized Data Management</h4>
</li>
</ol>
<p>Each microservice manages its own database or data store, ensuring data consistency and reducing dependencies between services. This decentralization helps in scaling and optimizing data access.</p>
<ol start="2">
<li><h4 id="heading-service-boundaries">Service Boundaries</h4>
</li>
</ol>
<p>Microservices are designed around business capabilities, and each service is responsible for a specific business function. This clear delineation of service boundaries helps in achieving a modular and organized system.</p>
<ol start="3">
<li><h4 id="heading-api-based-communication">API-Based Communication</h4>
</li>
</ol>
<p>Services communicate with each other using APIs (Application Programming Interfaces). This ensures that services remain loosely coupled and can interact without direct knowledge of each other’s implementation details.</p>
<ol start="4">
<li><h4 id="heading-independent-deployment">Independent Deployment</h4>
</li>
</ol>
<p>Each microservice can be developed, tested, and deployed independently. This allows teams to deploy updates to individual services without impacting the entire system, leading to faster release cycles.</p>
<ol start="5">
<li><h4 id="heading-technology-diversity">Technology Diversity</h4>
</li>
</ol>
<p>Microservices can use different technologies, frameworks, and programming languages based on their specific needs. This enables the use of the most suitable tools for each service.</p>
<ol start="6">
<li><h4 id="heading-fault-tolerance-and-resilience">Fault Tolerance and Resilience</h4>
</li>
</ol>
<p>The decentralized nature of microservices allows for better fault isolation. If one service fails, the rest of the system can continue to function, enhancing overall system resilience.</p>
<ol start="7">
<li><h4 id="heading-continuous-delivery-and-devops-practices">Continuous Delivery and DevOps Practices</h4>
</li>
</ol>
<p>Microservices align well with DevOps practices and continuous delivery models.<br>They enable automated testing, deployment, and monitoring, facilitating a more agile and iterative development process.</p>
<h3 id="heading-benefits-of-microservices">Benefits of Microservices</h3>
<ol>
<li><p><strong>Scalability and Flexibility</strong>: One of the standout advantages of microservices is their ability to scale specific components individually. For example, a service handling user traffic spikes, like a login service, can be scaled up independently without scaling the entire application, conserving resources and lowering operational costs.</p>
<ul>
<li><p>Imagine a restaurant where each kitchen station can expand its capacity independently. If more people order pizza, the pizza station can add more ovens without affecting the salad or dessert stations.</p>
<p>  <strong>Benefit:</strong> This flexibility makes microservices ideal for applications with varying workloads and dynamic growth patterns.</p>
</li>
</ul>
</li>
<li><p><strong>Independent Deployment and Development</strong>: Microservices allow teams to work on different services independently. This means that a change or deployment to one service does not necessitate changes or redeployments to other parts of the application, enhancing development speed and reducing downtime.</p>
<ul>
<li><p>Like a construction project where different teams (plumbing, electrical, carpentry) work independently on separate sections of a building, leading to faster overall completion.</p>
<p>  <strong>Benefit:</strong> Independent deployment reduces the risk of deploying new features or updates, as changes in one service do not directly impact others.</p>
</li>
</ul>
</li>
<li><p><strong>Fault Isolation and Resilience</strong>: In a microservices architecture, if one service fails, it does not necessarily bring down the entire application. For example, if a recommendation service in a streaming application fails, the core streaming functionality can continue to operate. This isolation makes applications more resilient and fault-tolerant.</p>
<ul>
<li><p>Consider a series of interconnected power grids. If one grid fails, the others continue to function, preventing a total blackout.</p>
<p>  <strong>Benefit:</strong> This fault isolation ensures higher availability and reliability, which is critical for modern applications that require constant uptime.</p>
</li>
</ul>
</li>
<li><p><strong>Technology Diversity and Optimization</strong>: Microservices enable teams to choose the best-suited technologies for each service. One service might benefit from being written in Python for data processing, while another might leverage JavaScript for its real-time, event-driven needs. This flexibility allows teams to optimize each service for performance, reliability, and maintainability.</p>
<ul>
<li><p>Similar to a craftsman selecting the best tool for each task, developers can use different programming languages, databases, and frameworks for different services.</p>
<p>  <strong>Benefit:</strong> This technology diversity enables teams to leverage the strengths of various tools, leading to more efficient and tailored solutions.</p>
</li>
</ul>
</li>
</ol>
<h3 id="heading-challenges-of-microservices">Challenges of Microservices</h3>
<p>While microservices provide significant benefits, they also come with their own set of challenges:</p>
<ol>
<li><p><strong>Complexity in Management and Orchestration</strong>: Microservices increase the complexity of managing multiple services, each with its own dependencies, configurations, and monitoring requirements. Tools like Kubernetes and Docker Swarm help orchestrate and manage these services, but they require additional setup and expertise.</p>
<ul>
<li><p>Like managing a fleet of ships in a convoy, where each ship must be coordinated, tracked, and directed, the complexity grows with the number of ships.</p>
<p>  <strong>Challenge:</strong> Organizations need to invest in orchestration tools like Kubernetes and service meshes to handle this complexity.</p>
</li>
</ul>
</li>
<li><p><strong>Data Consistency and Transaction Management</strong>: In monolithic systems, data consistency is easier to maintain because all components share a single database. With microservices, each service may have its own database, complicating transactions across services. Strategies like the Saga pattern or eventual consistency models are often employed to address this issue, though they can increase system complexity.</p>
<ul>
<li><p>Imagine trying to keep multiple ledgers synchronized across different offices.<br>  Ensuring that every ledger reflects the same transactions simultaneously can be difficult.</p>
<p>  <strong>Challenge:</strong> Developers often need to implement eventual consistency models and use patterns like Saga to manage distributed transactions.</p>
</li>
</ul>
</li>
<li><p><strong>Inter-Service Communication</strong>: Microservices rely heavily on network communication to exchange information. Issues like network latency, service timeouts, and retries can impact system performance. Choosing the right communication protocols (for example, REST, gRPC) and implementing practices like circuit breakers are essential for reliability.</p>
<ul>
<li><p>Like ensuring clear communication between different departments in a company, where messages need to be delivered quickly and accurately, and with the right level of security.</p>
<p>  <strong>Challenge:</strong> Developers must choose appropriate communication protocols (for example, REST, gRPC) and manage inter-service communication failures gracefully.</p>
</li>
</ul>
</li>
<li><p><strong>Security Considerations</strong>: Managing security in a microservices architecture is more complex, as each service needs its own access controls, authentication, and encryption measures. Technologies like OAuth2 and JWT (JSON Web Tokens) are commonly used to secure inter-service communication, but they require careful configuration and ongoing management.</p>
<ul>
<li><p>Like securing a multi-building campus where each building has its own security protocols, and ensuring that the entire campus remains secure requires careful planning.</p>
<p>  <strong>Challenge:</strong> Implementing security best practices, such as zero trust models and secure API gateways, is essential to protect microservices from threats.</p>
</li>
</ul>
</li>
</ol>
<p>The microservices architecture is an advanced, modular approach to building applications that prioritizes scalability, resilience, and flexibility.</p>
<p>While it offers substantial benefits over traditional monolithic architectures, especially in terms of independent service management, it also introduces new challenges in orchestration, communication, and security.</p>
<p>Understanding both the strengths and weaknesses of microservices is crucial for developers, architects, and business leaders aiming to make informed decisions about their application architecture.</p>
<h2 id="heading-microservices-vs-monolithic-architecture">Microservices vs Monolithic Architecture</h2>
<p>In a monolithic architecture, all components of an application—such as the user interface, business logic, and data layer—are interconnected within a single codebase.</p>
<p>This approach simplifies deployment and can be easier to start with, but it also has limitations.</p>
<p>As applications grow, a monolithic structure can become unwieldy, making it challenging to update or scale specific parts without affecting the entire system.</p>
<p>For instance, updating one feature in a monolithic application may require testing and redeploying the entire application, increasing both the time and potential risks involved.</p>
<p>Microservices, on the other hand, embrace a decentralized architecture, where each service can evolve independently.</p>
<p>This is ideal for complex applications where different teams can develop, test, and deploy their components independently.</p>
<p>But microservices do introduce additional complexity, such as managing service-to-service communication, handling data consistency across distributed services, and maintaining overall system security.</p>
<p>Despite these challenges, microservices offer a more modular, scalable approach that fits well with modern development and deployment practices, especially in agile and DevOps environments.</p>
<h4 id="heading-so-to-summarize-here-are-the-key-differences">So to summarize, here are the key differences:</h4>
<ol>
<li><h5 id="heading-structure">Structure</h5>
</li>
</ol>
<ul>
<li><p><strong>Monolithic:</strong> All functionalities are tightly integrated and managed within a single codebase. The application is usually deployed as a single unit.</p>
</li>
<li><p><strong>Microservices:</strong> The application is divided into multiple services, each with its own codebase, data storage, and deployment lifecycle.</p>
</li>
</ul>
<ol start="2">
<li><h5 id="heading-deployment">Deployment</h5>
</li>
</ol>
<ul>
<li><p><strong>Monolithic:</strong> Any change requires redeploying the entire application. This can lead to longer deployment cycles and higher risk of introducing bugs.</p>
</li>
<li><p><strong>Microservices:</strong> Services can be deployed independently, allowing for more frequent updates and easier rollback in case of issues.</p>
</li>
</ul>
<ol start="3">
<li><h5 id="heading-scalability">Scalability</h5>
</li>
</ol>
<ul>
<li><p><strong>Monolithic:</strong> Scaling requires scaling the entire application, which can be resource-intensive and inefficient.</p>
</li>
<li><p><strong>Microservices:</strong> Individual services can be scaled independently based on their specific load and requirements, leading to more efficient resource utilization.</p>
</li>
</ul>
<ol start="4">
<li><h5 id="heading-development-and-maintenance">Development and Maintenance</h5>
</li>
</ol>
<ul>
<li><p><strong>Monolithic:</strong> A single codebase can become large and complex, making it difficult to maintain and understand. Development can become slower as the codebase grows.</p>
</li>
<li><p><strong>Microservices:</strong> Each service is smaller and more focused, making it easier to manage and develop. Teams can work on different services simultaneously without interfering with each other.</p>
</li>
</ul>
<ol start="5">
<li><h5 id="heading-fault-isolation">Fault Isolation</h5>
</li>
</ol>
<ul>
<li><p><strong>Monolithic:</strong> A failure in one part of the application can affect the entire system.</p>
</li>
<li><p><strong>Microservices:</strong> Failures in one service do not necessarily impact other services, improving the overall fault tolerance of the system.</p>
</li>
</ul>
<h2 id="heading-core-microservices-concepts-and-components">Core Microservices Concepts and Components</h2>
<p>In this section, we’ll delve into the essential building blocks of microservices architecture, breaking down the principles and mechanisms that make it functional, scalable, and adaptable.</p>
<p>This section will cover key concepts such as service boundaries, API communication, and data management. Each component plays a vital role in enabling microservices to operate independently yet cohesively as part of a larger system.</p>
<p>You’ll explore the architectural practices that will let you deploy, scale, and manage microservices separately, while also understanding the importance of orchestration, inter-service communication, and monitoring.</p>
<p>These foundational elements are crucial for building reliable microservices applications and will provide a deeper look at the architecture's inner workings. This understanding will help you apply microservices principles effectively, ensuring that they add value to complex, distributed applications.</p>
<h3 id="heading-microservices-design-principles">Microservices Design Principles</h3>
<p>Here are some important principles to keep in mind when you’re designing microservices:</p>
<h4 id="heading-single-responsibility-principle">Single Responsibility Principle</h4>
<p>Each microservice should focus on a single responsibility or business capability.<br>This principle ensures that each service is specialized and manageable.</p>
<p>Think of a microservice as a specialized department in a company. For example, a company has separate departments for HR, Finance, and Sales, each handling its specific tasks.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// User Service - Manages user-related functionalities</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
  createUser(user) {
    <span class="hljs-comment">// Code to create a user</span>
  }
  getUser(userId) {
    <span class="hljs-comment">// Code to get a user by ID</span>
  }
}

<span class="hljs-comment">// Order Service - Manages order-related functionalities</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span> </span>{
  createOrder(order) {
    <span class="hljs-comment">// Code to create an order</span>
  }
  getOrder(orderId) {
    <span class="hljs-comment">// Code to get an order by ID</span>
  }
}
</code></pre>
<p>In this code, you can see how each class—<code>UserService</code> and <code>OrderService</code>—is created to focus on a single responsibility.</p>
<p>The <code>UserService</code> class is solely responsible for user-related tasks, such as creating a new user (<code>createUser(user)</code>) and retrieving a user by their ID (<code>getUser(userId)</code>).</p>
<p>By keeping these responsibilities separate, changes in user-related logic can be managed within <code>UserService</code> without affecting other services.</p>
<p>Similarly, <code>OrderService</code> is dedicated to managing order-related tasks, providing functions to create orders (<code>createOrder(order)</code>) and retrieve orders by their ID (<code>getOrder(orderId)</code>).</p>
<p>This approach aligns with the Single Responsibility Principle by ensuring that each service can evolve or scale based on its specific function without cross-dependencies.</p>
<p>For instance, if new features for handling complex user interactions are added, only <code>UserService</code> will require updates, leaving <code>OrderService</code> unaffected.</p>
<p>This isolation not only simplifies maintenance and testing but also supports independent scaling, as each service can be deployed, scaled, and optimized independently based on demand.</p>
<p>By encapsulating distinct business capabilities in individual services, this approach enables a cleaner, more modular, and manageable architecture—a crucial benefit for systems that may grow in complexity over time.</p>
<h4 id="heading-decentralized-data-management-1">Decentralized Data Management</h4>
<p>Each microservice manages its own database or data storage, avoiding shared databases between services.</p>
<p>Imagine each department in a company has its own filing cabinet. HR, Finance, and Sales each store their documents separately, so they don’t interfere with each other.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Simulating a decentralized database approach</span>
<span class="hljs-keyword">const</span> userDatabase = {}; <span class="hljs-comment">// Simulated database for user service</span>
<span class="hljs-keyword">const</span> orderDatabase = {}; <span class="hljs-comment">// Simulated database for order service</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
  createUser(user) {
    userDatabase[user.id] = user;
  }
  getUser(userId) {
    <span class="hljs-keyword">return</span> userDatabase[userId];
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span> </span>{
  createOrder(order) {
    orderDatabase[order.id] = order;
  }
  getOrder(orderId) {
    <span class="hljs-keyword">return</span> orderDatabase[orderId];
  }
}
</code></pre>
<p>In this code, you can see how each microservice independently manages its own data. Here’s how it works in detail:</p>
<ol>
<li><p><strong>Separate Data Stores</strong>: The <code>userDatabase</code> object simulates a standalone database dedicated to user data, while the <code>orderDatabase</code> object serves as a separate storage for order data. Each service accesses only its respective database, following the decentralized data management principle.</p>
</li>
<li><p><strong>UserService Class</strong>: The <code>UserService</code> class provides methods to create and retrieve user data. The <code>createUser</code> method adds a user to the <code>userDatabase</code>, using <a target="_blank" href="http://user.id"><code>user.id</code></a> as the unique key, and the <code>getUser</code> method retrieves a user based on their <code>userId</code>. This class is isolated from the <code>OrderService</code>, meaning changes to user-related logic or data will not interfere with order data.</p>
</li>
<li><p><strong>OrderService Class</strong>: Similarly, the <code>OrderService</code> class manages its own data. The <code>createOrder</code> method stores an order in the <code>orderDatabase</code>, with <a target="_blank" href="http://order.id"><code>order.id</code></a> serving as a unique identifier, and <code>getOrder</code> retrieves an order by its ID.</p>
</li>
</ol>
<p>By isolating data management responsibilities to each service, this code snippet ensures that the user-related and order-related data remain distinct.</p>
<p>This reduces interdependencies between services, which is crucial for achieving high reliability and scalability in a microservices architecture.</p>
<p>In a real-world scenario, each microservice would likely use a separate database instance (for example, separate SQL or NoSQL databases) rather than simple objects, but the principle remains the same.</p>
<p>Each service has full ownership and control over its data, which allows for independent scaling, maintenance, and updates without affecting other services.</p>
<h4 id="heading-api-first-design">API-First Design</h4>
<p>It’s a good idea to design APIs before implementing the services to ensure clear interaction contracts between services.</p>
<p>Before building a bridge, engineers create detailed blueprints to define how vehicles and pedestrians will use it. Similarly, designing APIs defines how services will communicate.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Define API contract for User Service</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUser</span>(<span class="hljs-params">user</span>) </span>{
  <span class="hljs-comment">// POST /users endpoint</span>
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUser</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-comment">// GET /users/:id endpoint</span>
}

<span class="hljs-comment">// Define API contract for Order Service</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createOrder</span>(<span class="hljs-params">order</span>) </span>{
  <span class="hljs-comment">// POST /orders endpoint</span>
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getOrder</span>(<span class="hljs-params">orderId</span>) </span>{
  <span class="hljs-comment">// GET /orders/:id endpoint</span>
}
</code></pre>
<p>In the code above, you can see how each function represents a different API endpoint, specifying the action that each endpoint should perform and the HTTP methods associated with each action.</p>
<p>This allows for an organized approach to creating APIs for our services and ensures that each service's interface is clearly defined before implementation.</p>
<p>Here’s how each function works and the purpose it serves:</p>
<ul>
<li><p>The functions <code>createUser(user)</code> and <code>getUser(userId)</code> are defined for the <code>User Service</code>, representing the expected API contract for handling user data.</p>
<p>  The <code>createUser</code> function corresponds to a <code>POST /users</code> endpoint, indicating that this function is designed to create a new user.</p>
<p>  The choice of the <code>POST</code> method is intentional, as it aligns with standard HTTP practices for creating resources. This endpoint would typically accept a <code>user</code> object as input in the request body and save that data in the user service's database.</p>
</li>
<li><p>The <code>getUser(userId)</code> function, represented by a <code>GET /users/:id</code> endpoint, is designed to retrieve a user's information based on their unique identifier, <code>userId</code>.</p>
<p>  The <code>GET</code> method reflects a read operation, meaning this endpoint will fetch data rather than modify it.</p>
<p>  Similarly, the <code>Order Service</code> has two endpoint definitions, <code>createOrder(order)</code> and <code>getOrder(orderId)</code>, corresponding to <code>POST /orders</code> and <code>GET /orders/:id</code> endpoints, respectively.</p>
</li>
<li><p>The <code>createOrder</code> function is intended to handle new order creation, taking an <code>order</code> object and saving it within the service.</p>
</li>
<li><p>The <code>getOrder</code> function retrieves order details based on the <code>orderId</code>, providing the necessary data for the requesting client or service.</p>
</li>
</ul>
<p>By defining these endpoints upfront, the API-First Design approach emphasizes creating a clear and well-documented blueprint for how each service should be used.</p>
<p>This approach is comparable to engineers designing blueprints before building a bridge—where these API “blueprints” ensure that services can reliably interact with one another.</p>
<p>These API contracts serve as a formalized communication agreement between services, reducing the risk of misinterpretation or errors during integration.</p>
<h4 id="heading-autonomous-deployment-and-scaling">Autonomous Deployment and Scaling</h4>
<p>Each microservice can be deployed and scaled independently of others.</p>
<p>Imagine each department in a company has its own office space.<br>If the HR department grows, it can expand its office without affecting the Sales department’s office.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Simulated deployment and scaling</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
  deploy() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Deploying User Service..."</span>);
  }
  scale() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Scaling User Service..."</span>);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span> </span>{
  deploy() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Deploying Order Service..."</span>);
  }
  scale() {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Scaling Order Service..."</span>);
  }
}

<span class="hljs-keyword">const</span> userService = <span class="hljs-keyword">new</span> UserService();
<span class="hljs-keyword">const</span> orderService = <span class="hljs-keyword">new</span> OrderService();

userService.deploy();
orderService.deploy();

userService.scale();
</code></pre>
<p>In the code above, you can see how each service is treated independently with its own methods for deployment and scaling.</p>
<ul>
<li><p>The <code>UserService</code> and <code>OrderService</code> classes both contain <code>deploy()</code> and <code>scale()</code> methods that simulate the ability to launch and adjust the resources dedicated to each service individually.</p>
</li>
<li><p>The <code>deploy()</code> method in each class outputs a message that reflects the action of deploying the service. This action is critical in a cloud environment where services must be managed remotely, often across distributed infrastructure.</p>
<p>  Deployment here means making the service available to handle requests, such as by creating new instances of the service in the cloud.</p>
</li>
<li><p>The <code>scale()</code> method simulates increasing the resources allocated to each service, an essential feature in microservices architectures where scaling allows a service to handle an increased load.</p>
<p>  For instance, if there is a high demand for user-related actions, only the <code>UserService</code> needs to scale, without impacting the resources or operations of <code>OrderService</code>.</p>
</li>
</ul>
<p>This approach, much like how each department in a company might manage its office space, allows for resource allocation to be both responsive and resource-efficient.</p>
<p>By creating separate instances for <code>userService</code> and <code>orderService</code> and then calling the <code>deploy()</code> and <code>scale()</code> methods, the code highlights how, in practice, these services are intended to operate independently.</p>
<p>This independent operation is fundamental in microservices, ensuring that each service can be scaled or deployed as needed based on demand or new releases, without disrupting or overburdening other parts of the system.</p>
<h3 id="heading-service-communication-synchronous-vs-asynchronous">Service Communication: Synchronous vs Asynchronous</h3>
<h5 id="heading-well-discuss-two-types-of-communication-here-synchronous-and-asynchronous-communication-lets-start-with-the-synchronous-variety">We’ll discuss two types of communication here: Synchronous and. Asynchronous communication. Let’s start with the synchronous variety.</h5>
<p>In <strong>synchronous</strong> <strong>communication</strong>, services wait for a response from another service before continuing. This is like making a phone call where you wait for the person on the other end to respond.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchUser</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/users/<span class="hljs-subst">${userId}</span>`</span>);
  <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> response.json();
  <span class="hljs-keyword">return</span> user;
}
</code></pre>
<p>In the code above, you can see how the function uses the <code>fetch</code> API to send a request to a specified endpoint (<code>/users/${userId}</code>).</p>
<p>Here’s how it works in detail:</p>
<ol>
<li><p><strong>Request Setup</strong>: When <code>fetchUser</code> is called, it takes <code>userId</code> as a parameter and builds a request to an endpoint. The URL (<code>/users/${userId}</code>) is set up to retrieve information specifically for that user.</p>
</li>
<li><p><strong>Awaiting the Response</strong>: Using <code>await</code>, the function pauses execution until the response arrives from the server. This is the core of synchronous communication: the function stops and waits rather than moving to the next line immediately.</p>
</li>
<li><p><strong>Extracting Data</strong>: After the server responds, <code>await response.json()</code> extracts the user data from the response as JSON.</p>
</li>
<li><p><strong>Returning Data</strong>: Finally, the function returns the <code>user</code> object containing the requested user data.</p>
</li>
</ol>
<p>This synchronous approach is useful when a service depends on data from another service to continue processing.</p>
<p>For instance, if an e-commerce microservice needs user details before creating an order, it might pause at this point, waiting until <code>fetchUser</code> retrieves the required data. This ensures that all necessary information is available before moving forward.</p>
<p>In <strong>asynchronous</strong> <strong>communication</strong>, on the other hand, services send messages and continue processing without waiting for a response.</p>
<p>This is like sending a letter in the mail. You don’t wait for the recipient’s reply before continuing with your day.</p>
<pre><code class="lang-javascript"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params">queue, message</span>) </span>{
  <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Message sent to <span class="hljs-subst">${queue}</span>: <span class="hljs-subst">${message}</span>`</span>);
  }, <span class="hljs-number">1000</span>); <span class="hljs-comment">// Simulate asynchronous operation</span>
}

sendMessage(<span class="hljs-string">'orderQueue'</span>, <span class="hljs-string">'New order created'</span>);
</code></pre>
<p>In this code example, the <code>sendMessage</code> function takes two arguments: <code>queue</code> and <code>message</code>. Here:</p>
<ul>
<li><p><strong>queue</strong>: Represents the name of the message queue, which is the target for the message. Think of it as the destination where the message will be processed asynchronously, like "orderQueue" in this example.</p>
</li>
<li><p><strong>message</strong>: The content or payload of the message being sent, here being <code>"New order created"</code>.</p>
</li>
</ul>
<p>The <code>setTimeout</code> function is used to simulate an asynchronous operation by delaying the <code>console.log</code> output for 1 second (1000 milliseconds).</p>
<p>This delay represents the time it might take for the message to be sent and processed, though, in reality, the actual sending happens instantly, allowing the program to continue processing other tasks without waiting.</p>
<p>After calling <code>sendMessage</code>, the program doesn’t wait for any confirmation and immediately continues with its other operations, reflecting the <strong>non-blocking nature</strong> of asynchronous communication in microservices.</p>
<p>And in this code, you can see how <code>setTimeout</code> simulates asynchronous behavior by delaying the message output to demonstrate that <code>sendMessage</code> doesn’t hold up any further actions while it "sends" the message.</p>
<p>This mirrors the real-world asynchronous messaging between microservices, where they communicate by posting messages to queues or topics without waiting for an immediate reply.</p>
<p>This approach helps systems stay decoupled and scalable by allowing different services to operate independently, even if they depend on one another for data.</p>
<h3 id="heading-restful-apis"><strong>RESTful APIs</strong></h3>
<p>REST (Representational State Transfer) uses standard HTTP methods (GET, POST, PUT, DELETE) for service communication.</p>
<p>Think of RESTful APIs like a menu in a restaurant. Each item on the menu (endpoint) corresponds to a specific request (for example, GET to retrieve, POST to create).</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Fetch user using RESTful API</span>
<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUser</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">`/api/users/<span class="hljs-subst">${userId}</span>`</span>);
  <span class="hljs-keyword">const</span> user = <span class="hljs-keyword">await</span> response.json();
  <span class="hljs-keyword">return</span> user;
}
</code></pre>
<p>This code demonstrates the use of a <strong>RESTful API</strong> to fetch user data based on a unique <code>userId</code> identifier.</p>
<p>RESTful APIs rely on a standardized set of HTTP methods—such as <code>GET</code>, <code>POST</code>, <code>PUT</code>, and <code>DELETE</code>—to interact with resources.</p>
<p>In this example, the <code>fetch</code> API is used to retrieve user data from a specified endpoint (<code>/api/users/${userId}</code>) by issuing a <code>GET</code> request.</p>
<p>This method is asynchronous, which allows the code to wait for the response without blocking other processes.</p>
<p>Here’s how each part of the code functions:</p>
<ol>
<li><p><strong>Function Definition</strong>: <code>getUser</code> is an <code>async</code> function, meaning it returns a Promise and can utilize the <code>await</code> keyword for asynchronous operations, making it ideal for handling HTTP requests that may take time to return.</p>
</li>
<li><p><strong>Fetching Data</strong>: Within <code>getUser</code>, the <code>fetch</code> function initiates an HTTP <code>GET</code> request to the specified URL endpoint (<code>/api/users/${userId}</code>). This URL is dynamically generated based on the <code>userId</code> provided when the function is called. Here, <code>fetch</code> represents an API request to retrieve a user's information, acting similarly to ordering a specific item from a menu in a restaurant based on a user-supplied request.</p>
</li>
<li><p><strong>Parsing JSON</strong>: After receiving the response from the server, <code>await response.json()</code> is used to parse the JSON data, which contains the user’s information. JSON (JavaScript Object Notation) is the most common format for data exchange in REST APIs, making it easy for different services to communicate with one another.</p>
</li>
<li><p><strong>Return Value</strong>: Once the data is parsed, it’s returned as a JavaScript object containing the user’s information, which can then be utilized elsewhere in the application.</p>
</li>
</ol>
<p>In this code, you can see how the asynchronous nature of <code>fetch</code> and <code>await</code> works to ensure that the function doesn’t block the program while waiting for the response.</p>
<p>This approach allows the function to perform RESTful communication efficiently, reflecting how microservices interact seamlessly via HTTP requests to fetch, update, or delete resources without impacting the rest of the system.</p>
<h3 id="heading-grpc-and-protocol-buffers"><strong>gRPC and Protocol Buffers</strong></h3>
<p>gRPC is a high-performance RPC framework that uses Protocol Buffers for serialization.</p>
<p>gRPC and Protocol Buffers are like a highly efficient postal service that uses a compact and precise form to send messages quickly.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// gRPC server setup</span>
<span class="hljs-keyword">const</span> grpc = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@grpc/grpc-js'</span>);
<span class="hljs-keyword">const</span> protoLoader = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@grpc/proto-loader'</span>);
<span class="hljs-keyword">const</span> packageDefinition = protoLoader.loadSync(<span class="hljs-string">'user.proto'</span>);
<span class="hljs-keyword">const</span> userProto = grpc.loadPackageDefinition(packageDefinition).user;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUser</span>(<span class="hljs-params">call, callback</span>) </span>{
  <span class="hljs-comment">// Implementation here</span>
}

<span class="hljs-keyword">const</span> server = <span class="hljs-keyword">new</span> grpc.Server();
server.addService(userProto.UserService.service, { getUser });
server.bind(<span class="hljs-string">'127.0.0.1:50051'</span>, grpc.ServerCredentials.createInsecure());
server.start();
</code></pre>
<p>This code sets up a basic <strong>gRPC server</strong> using Protocol Buffers to define the structure and communication format of messages between the client and server.</p>
<p>gRPC (Google Remote Procedure Call) is a high-performance framework that uses <strong>Protocol Buffers</strong> (protobuf) for efficient serialization and deserialization of data.</p>
<p>This setup allows for fast and secure communication between microservices, particularly useful in distributed systems.</p>
<p>Here’s how each part of the code works:</p>
<ol>
<li><p><strong>Library Imports</strong>: The code first imports the necessary gRPC library (<code>grpc</code>) and a Protocol Buffer loader (<code>@grpc/proto-loader</code>). These tools are essential for creating a gRPC server and handling Protocol Buffer files.</p>
</li>
<li><p><strong>Loading Protocol Buffer Definition</strong>: The line <code>protoLoader.loadSync('user.proto')</code> loads a Protocol Buffer file called <code>user.proto</code>. This file defines the structure of the <code>UserService</code> and its <code>getUser</code> method. After loading the Protocol Buffer file, the <code>grpc.loadPackageDefinition()</code> function converts the package definition into a usable JavaScript object, making the <code>userProto</code> service available to the server.</p>
</li>
<li><p><strong>Defining the getUser Function</strong>: The <code>getUser</code> function is a placeholder for handling incoming <code>getUser</code> requests. The function uses two parameters: <code>call</code>, which contains request data sent by the client, and <code>callback</code>, which sends back a response. In a production implementation, this function would interact with a database or perform other business logic before responding.</p>
</li>
<li><p><strong>Setting up the Server</strong>: The code initializes a new gRPC server with <code>const server = new grpc.Server()</code>. This server will listen for client requests and respond according to the services and methods defined in the Protocol Buffer.</p>
</li>
<li><p><strong>Adding the Service</strong>: The line <code>server.addService(userProto.UserService.service, { getUser })</code> registers the <code>UserService</code> service and assigns it the <code>getUser</code> function as the handler for its requests.</p>
</li>
<li><p><strong>Binding the Server to an Address</strong>: The server is then bound to the local address <code>127.0.0.1</code> and port <code>50051</code> for listening to incoming requests. Here, <code>grpc.ServerCredentials.createInsecure()</code> sets up an insecure connection. In a real-world application, you’d typically use SSL/TLS certificates for secure communication.</p>
</li>
<li><p><strong>Starting the Server</strong>: Finally, <code>server.start()</code> begins listening for requests on the specified address and port.</p>
</li>
</ol>
<p>In the code, you can see how the gRPC framework, along with Protocol Buffers, is used to create an efficient and structured server-client communication channel.</p>
<p>This setup enables microservices to communicate rapidly and precisely by using protobuf, which is more compact than JSON or XML and allows for faster message parsing.</p>
<p>This is similar to a well-organized postal service where both the sender and receiver understand the same structured language, ensuring quick and accurate message delivery between services.</p>
<h3 id="heading-message-brokers-like-rabbitmq-and-kafka"><strong>Message Brokers (like RabbitMQ and Kafka)</strong></h3>
<p>Message brokers manage and route messages between services, enabling asynchronous communication.</p>
<p>A message broker is like a post office that handles and delivers messages between senders and receivers.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> amqp = <span class="hljs-built_in">require</span>(<span class="hljs-string">'amqplib'</span>);

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">sendMessage</span>(<span class="hljs-params">queue, message</span>) </span>{
  <span class="hljs-keyword">const</span> connection = <span class="hljs-keyword">await</span> amqp.connect(<span class="hljs-string">'amqp://localhost'</span>);
  <span class="hljs-keyword">const</span> channel = <span class="hljs-keyword">await</span> connection.createChannel();
  <span class="hljs-keyword">await</span> channel.assertQueue(queue);
  channel.sendToQueue(queue, Buffer.from(message));
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Message sent to <span class="hljs-subst">${queue}</span>: <span class="hljs-subst">${message}</span>`</span>);
  <span class="hljs-keyword">await</span> connection.close();
}

sendMessage(<span class="hljs-string">'orderQueue'</span>, <span class="hljs-string">'New order created'</span>);
</code></pre>
<p>This code demonstrates how to send a message to a <strong>RabbitMQ</strong> message queue using the <code>amqplib</code> library in Node.js. Message brokers like RabbitMQ act as intermediaries, managing and routing messages between services asynchronously.</p>
<p>They help decouple services, meaning that services don’t need to wait for responses to continue functioning. RabbitMQ is particularly useful in microservices architectures for distributing tasks, such as order processing or notifications.</p>
<p>Here’s how each part of this code works:</p>
<p>In the code above, you can see how message passing between services is accomplished using RabbitMQ. The <code>sendMessage</code> function encapsulates the message-sending process:</p>
<ol>
<li><p><strong>Connecting to RabbitMQ</strong>: The line <code>const connection = await amqp.connect('amqp://</code><a target="_blank" href="http://localhost"><code>localhost</code></a><code>');</code> establishes a connection to the RabbitMQ server. Here, <code>amqp://</code><a target="_blank" href="http://localhost"><code>localhost</code></a> refers to a locally hosted RabbitMQ instance. In a production environment, this would typically be a remote server URL.</p>
</li>
<li><p><strong>Creating a Channel</strong>: The <code>await connection.createChannel();</code> line creates a <strong>channel</strong> for sending messages. Channels are lightweight connections over which data can be sent and received. Each channel operates independently, so multiple channels can be used simultaneously without interfering with each other.</p>
</li>
<li><p><strong>Declaring the Queue</strong>: By calling <code>await channel.assertQueue(queue);</code>, the code ensures that the specified queue (<code>orderQueue</code> in this case) exists. If it doesn’t exist, RabbitMQ will create it. This declaration helps RabbitMQ know where the message should be sent.</p>
</li>
<li><p><strong>Sending the Message</strong>: The line <code>channel.sendToQueue(queue, Buffer.from(message));</code> sends the message to the specified queue by converting it to a <code>Buffer</code>. Buffers handle binary data, which is how RabbitMQ expects messages to be sent. In this case, the message <code>"New order created"</code> is sent to <code>orderQueue</code>.</p>
</li>
<li><p><strong>Closing the Connection</strong>: Finally, <code>await connection.close();</code> closes the connection to RabbitMQ, ensuring that resources are freed up after the message has been sent.</p>
</li>
</ol>
<p>This setup is similar to a post office that receives and distributes mail. Just as a post office routes letters to their recipients, RabbitMQ ensures messages reach the correct service queues, allowing services to process them when they’re ready.</p>
<p>This code shows how RabbitMQ’s asynchronous communication helps prevent services from blocking each other, enabling a more scalable, reliable application design.</p>
<h2 id="heading-data-management-in-microservices">Data Management in Microservices</h2>
<h3 id="heading-database-per-service-pattern">Database per Service Pattern</h3>
<p>Each microservice has its own database, ensuring data encapsulation and independence.</p>
<p>And each department in a company has its own filing system, ensuring that data is kept separate and managed independently.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Simulating separate databases for User and Order services</span>
<span class="hljs-keyword">const</span> userDatabase = {};
<span class="hljs-keyword">const</span> orderDatabase = {};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addUser</span>(<span class="hljs-params">user</span>) </span>{
  userDatabase[user.id] = user;
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addOrder</span>(<span class="hljs-params">order</span>) </span>{
  orderDatabase[order.id] = order;
}
</code></pre>
<p>In this code, you can see how <strong>separate databases</strong> are being simulated for the <code>User</code> and <code>Order</code> services. Each microservice manages its own isolated database (<code>userDatabase</code> and <code>orderDatabase</code>), ensuring that the data for users and orders is kept separate, just like how different departments within a company manage their own filing systems to avoid interference.</p>
<ol>
<li><p><strong>User Service Database</strong>: The <code>userDatabase</code> object acts as the storage for all user-related data. The <code>addUser</code> function adds new users to this database by storing user information with a unique <code>user.id</code> as the key. This means that all user data is managed and stored by the User Service independently of any other service.</p>
</li>
<li><p><strong>Order Service Database</strong>: Similarly, the <code>orderDatabase</code> object stores all order-related data, with the <code>addOrder</code> function adding orders using their unique <code>order.id</code>. Again, the order data is managed and stored by the Order Service independently, without any interference from the User Service.</p>
</li>
</ol>
<p>The key concept demonstrated here is the <strong>Database per Service</strong> pattern, which is a fundamental aspect of microservices architectures.</p>
<p>By ensuring that each service (for example, User Service, Order Service) has its own database, you prevent issues related to tight coupling between services.</p>
<p>Each service can evolve and scale independently, managing its own data in a way that best suits its functionality.</p>
<p>In this scenario, if the <code>User</code> service needs to change its database schema (for example, adding more fields to the user data), it can do so without affecting the <code>Order</code> service.</p>
<p>Similarly, if the <code>Order</code> service needs to optimize its data management or scale independently, it can do so without relying on the <code>User</code> service's database.</p>
<p>This approach makes each service self-contained, thus supporting easier maintenance and greater scalability.</p>
<h3 id="heading-data-consistency-and-synchronization">Data Consistency and Synchronization</h3>
<p>Ensuring consistency across services and handling data synchronization challenges are key when working with microservices.</p>
<p>This is like synchronizing calendars across multiple devices to ensure all appointments are up-to-date.</p>
<p>There are various strategies you can use to handle these issues:</p>
<ol>
<li><h5 id="heading-event-sourcing"><strong>Event Sourcing</strong></h5>
</li>
</ol>
<h5 id="heading-event-sourcing-involves-storing-changes-to-data-as-a-sequence-of-events-rather-than-a-single-state-its-like-keeping-a-diary-of-every-change-rather-than-just-recording-the-final-status">Event sourcing involves storing changes to data as a sequence of events rather than a single state. It’s like keeping a diary of every change rather than just recording the final status.</h5>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> events = []; <span class="hljs-comment">// Event log</span>

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">addUserEvent</span>(<span class="hljs-params">user</span>) </span>{
  events.push({ <span class="hljs-attr">type</span>: <span class="hljs-string">'USER_CREATED'</span>, <span class="hljs-attr">payload</span>: user });
}

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">replayEvents</span>(<span class="hljs-params"></span>) </span>{
  events.forEach(<span class="hljs-function"><span class="hljs-params">event</span> =&gt;</span> {
    <span class="hljs-keyword">if</span> (event.type === <span class="hljs-string">'USER_CREATED'</span>) {
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Replaying event:'</span>, event.payload);
    }
  });
}
</code></pre>
<p>In the code above, you can see how <strong>events are logged and replayed</strong> in an event-sourcing pattern:</p>
<ul>
<li><p><strong>Event Logging with</strong> <code>addUserEvent</code>: The <code>addUserEvent</code> function simulates adding a "user created" event to an event log (<code>events</code> array). Each event includes a <code>type</code> property, which identifies the type of event (in this case, <code>'USER_CREATED'</code>), and a <code>payload</code> property that contains the actual data for the event. Every time a new user is created, the <code>addUserEvent</code> function captures this change as a new entry in the <code>events</code> array, keeping a record of the action.</p>
</li>
<li><p><strong>Replaying Events with</strong> <code>replayEvents</code>: The <code>replayEvents</code> function demonstrates how to go through the recorded events and process them. It iterates over each event in the <code>events</code> array, checking the <code>type</code> of each event. If an event is of type <code>'USER_CREATED'</code>, it logs the payload of the event. This replaying process is central to event sourcing, as it enables the system to "recreate" the state based on the sequence of events. Here, the <code>console.log</code> statement serves as a placeholder, which could be replaced with any logic needed to actually apply or process the event data.</p>
</li>
</ul>
<p>This example illustrates the <strong>event sourcing principle</strong> of retaining a record of each significant change as a discrete event, rather than just updating the state directly.</p>
<p>By capturing changes as events, we gain a historical log of all actions, which can be replayed for auditing, debugging, or reconstructing the system state at any specific point in time.</p>
<p>This concept is similar to maintaining a detailed diary rather than just summarizing the current state—each entry preserves context about changes that occurred over time.</p>
<ol start="2">
<li><h5 id="heading-cqrs-command-query-responsibility-segregation"><strong>CQRS (Command Query Responsibility Segregation)</strong></h5>
</li>
</ol>
<p>This involves separating command (write) and query (read) operations.</p>
<p>It’s like having separate teams for handling customer service requests (commands) and handling customer inquiries (queries).</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Command: Modify data</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">createUser</span>(<span class="hljs-params">user</span>) </span>{
  <span class="hljs-comment">// Code to create user</span>
}

<span class="hljs-comment">// Query: Retrieve data</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getUser</span>(<span class="hljs-params">userId</span>) </span>{
  <span class="hljs-comment">// Code to get user</span>
}
</code></pre>
<p>In this code, you can see <strong>how commands and queries are separated</strong> in CQRS:</p>
<ul>
<li><p><strong>Command -</strong> <code>createUser</code>: The <code>createUser</code> function represents a command. In the context of CQRS, a command is an operation that modifies the state of the application. Here, <code>createUser</code> would include logic to add a new user to the system, modifying the database by inserting new user data. Commands in CQRS focus solely on changing the data: they don’t return the updated data or information about the system state but rather indicate an action to be performed.</p>
</li>
<li><p><strong>Query -</strong> <code>getUser</code>: The <code>getUser</code> function represents a query. In CQRS, queries are used solely to retrieve data without altering the system state. This function could contain logic to look up and return user information based on the provided <code>userId</code>. Since queries only retrieve data, they don’t impact the underlying data and can be optimized for fast reads, enabling the system to scale read operations as needed.</p>
</li>
</ul>
<p>By separating these operations into distinct functions, CQRS helps enforce the idea that reading and modifying data should not be intermixed.</p>
<p>This separation improves clarity, as each function has a clear purpose and responsibility.</p>
<p>It also allows the system to handle high volumes of read requests without impacting write operations (and vice versa), making the architecture more resilient and scalable for complex applications.</p>
<p>The analogy to separate teams handling different tasks is helpful here. Just as one team might handle customer service requests (for example, resolving issues or making changes) and another team handles customer inquiries (for example, answering questions or providing information), the code separates commands and queries into distinct functions for specialized purposes.</p>
<h2 id="heading-service-discovery-and-load-balancing">Service Discovery and Load Balancing</h2>
<h3 id="heading-service-discovery-mechanisms">Service Discovery Mechanisms</h3>
<p>Service discovery mechanisms help you automatically locate and interact with services in a distributed system.</p>
<p>It’s like a company directory where employees can find the contact details of their colleagues.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Simulated service discovery using a mock service discovery</span>
<span class="hljs-keyword">const</span> services = {
  <span class="hljs-attr">userService</span>: <span class="hljs-string">'http://localhost:3001'</span>,
  <span class="hljs-attr">orderService</span>: <span class="hljs-string">'http://localhost:3002'</span>
};

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getServiceUrl</span>(<span class="hljs-params">serviceName</span>) </span>{
  <span class="hljs-keyword">return</span> services[serviceName];
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User Service URL:'</span>, getServiceUrl(<span class="hljs-string">'userService'</span>));
</code></pre>
<p>In this code, you can see how <strong>service discovery is implemented</strong> with a simple lookup structure:</p>
<ol>
<li><p><strong>Service Directory (Mock Service Discovery)</strong>: The <code>services</code> object acts as a mock directory that maps service names (like <code>userService</code> and <code>orderService</code>) to their URLs (for example, <a target="_blank" href="http://localhost:3001"><code>http://localhost:3001</code></a> for the User Service). In real-world applications, this directory would be managed by a dedicated service discovery tool (such as Consul, Eureka, or etcd) rather than a static object. These tools keep track of available service instances and their locations, handling updates when services start or stop.</p>
</li>
<li><p><strong>Dynamic URL Resolution</strong>: The <code>getServiceUrl</code> function accepts a service name as an argument and returns the corresponding URL by looking it up in the <code>services</code> directory. Here, the code <code>getServiceUrl('userService')</code> returns <a target="_blank" href="http://localhost:3001"><code>http://localhost:3001</code></a>. This allows a client or another service to dynamically resolve and access the URL for <code>userService</code>, decoupling the services by avoiding hardcoded URLs.</p>
</li>
<li><p><strong>Example Output</strong>: The final <code>console.log</code> line demonstrates fetching the User Service URL using the <code>getServiceUrl</code> function, allowing dynamic access. The returned URL can be used by other services to make HTTP requests to the User Service.</p>
</li>
</ol>
<p>The analogy here is like using a <strong>company directory</strong> to look up a colleague's contact details rather than remembering each individual’s location or number.</p>
<p>In a microservices architecture, service discovery mechanisms like this make the system more resilient and flexible, as services can be added, removed, or scaled without directly impacting other services that depend on them.</p>
<h3 id="heading-load-balancing-strategies"><strong>Load Balancing Strategies</strong></h3>
<p>Load balancing involves distributing network traffic across multiple servers to ensure efficient use of resources.</p>
<p>It’s like a traffic light that directs cars to different lanes to manage traffic flow.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Simulated load balancing</span>
<span class="hljs-keyword">const</span> servers = [<span class="hljs-string">'http://localhost:3001'</span>, <span class="hljs-string">'http://localhost:3002'</span>];

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getServer</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> servers[<span class="hljs-built_in">Math</span>.floor(<span class="hljs-built_in">Math</span>.random() * servers.length)];
}

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Selected Server:'</span>, getServer());
</code></pre>
<p>In the code above, you can see how <strong>load balancing is simulated</strong> using an array of server URLs and a simple randomization technique:</p>
<ol>
<li><p><strong>Server Pool</strong>: The <code>servers</code> array contains a list of URLs representing different servers or instances of the same service (for example, two instances of a web application running on different ports, <a target="_blank" href="http://localhost:3001"><code>http://localhost:3001</code></a> and <a target="_blank" href="http://localhost:3002"><code>http://localhost:3002</code></a>). In a production environment, this list would typically include the actual IP addresses or URLs of servers that can handle the load.</p>
</li>
<li><p><strong>Random Load Balancing Strategy</strong>: The <code>getServer</code> function picks a server at random by selecting an index within the <code>servers</code> array. It generates a random number using <code>Math.random()</code> and multiplies it by the length of the <code>servers</code> array. Then, <code>Math.floor()</code> rounds this value down to the nearest whole number, ensuring it corresponds to a valid index in the <code>servers</code> array. This strategy simulates <strong>random load balancing</strong> by choosing one server for each request, which can help distribute requests fairly evenly in smaller setups.</p>
</li>
<li><p><strong>Output</strong>: Finally, <code>console.log('Selected Server:', getServer());</code> demonstrates which server was selected. Each time <code>getServer()</code> is called, it may pick a different server, showing how incoming requests would be balanced across the available options.</p>
</li>
</ol>
<p>In real-world scenarios, load balancers often use more sophisticated strategies, such as <strong>round-robin</strong> (cycling through servers in sequence) or <strong>least connections</strong> (sending traffic to the server with the fewest active connections).</p>
<p>The analogy here is like a <strong>traffic light directing cars into different lanes</strong>: each lane is a server, and the traffic light (load balancer) distributes vehicles (requests) to prevent congestion.</p>
<p>This simple load-balancing code illustrates the concept of spreading requests across servers, which can improve performance and system resilience by reducing the chances of overloading any single server.</p>
<h2 id="heading-how-to-build-and-design-microservices"><strong>How to Build and Design Microservices</strong></h2>
<p>In this section, I’ll guide you through the process of designing and developing microservices, focusing on best practices and practical techniques for creating effective, resilient services.</p>
<p>We’ll cover essential steps like setting up a microservices environment, structuring services for modularity, and choosing the right tools and frameworks to streamline development.</p>
<p>You will learn about key aspects of service creation, including defining service boundaries, establishing inter-service communication, and implementing APIs for seamless integration.</p>
<p>We’ll also explore important considerations like data management, security, and deployment strategies specific to microservices.</p>
<p>By the end of this section, you'll have a comprehensive understanding of the techniques and tools that support efficient microservices development, providing a strong foundation for creating scalable, flexible, and high-performing microservices-based applications.</p>
<h3 id="heading-define-service-boundaries"><strong>Define Service Boundaries</strong></h3>
<p>It’s important to identify the distinct business functions that each microservice will handle. This involves defining clear responsibilities and interfaces.</p>
<p>Think of service boundaries like different departments in a company. Each department (HR, Sales, Support) has a clear function and operates independently.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Define service boundaries</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.users = []; <span class="hljs-comment">// Manages user-related data</span>
  }

  createUser(user) {
    <span class="hljs-built_in">this</span>.users.push(user);
    <span class="hljs-keyword">return</span> user;
  }

  getUser(userId) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.users.find(<span class="hljs-function"><span class="hljs-params">user</span> =&gt;</span> user.id === userId);
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.orders = []; <span class="hljs-comment">// Manages order-related data</span>
  }

  createOrder(order) {
    <span class="hljs-built_in">this</span>.orders.push(order);
    <span class="hljs-keyword">return</span> order;
  }

  getOrder(orderId) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.orders.find(<span class="hljs-function"><span class="hljs-params">order</span> =&gt;</span> order.id === orderId);
  }
}
</code></pre>
<p>In this code, you can see how <strong>each service has its own distinct responsibilities</strong>:</p>
<ol>
<li><p><strong>UserService</strong>: This class is dedicated to managing user-related data and functionalities. The <code>this.users</code> array simulates a database, storing user data exclusively within the <code>UserService</code> scope. The <code>createUser</code> method allows for adding a new user to this array, while <code>getUser</code> retrieves a user by their ID. By defining these methods within <code>UserService</code>, the code makes sure that all user-related data is encapsulated and handled only within this service, ensuring clear separation from other services.</p>
</li>
<li><p><strong>OrderService</strong>: Similarly, <code>OrderService</code> is exclusively responsible for order-related data and operations. It maintains its own <code>this.orders</code> array to store order data and provides <code>createOrder</code> and <code>getOrder</code> methods to add and retrieve orders, respectively. Like <code>UserService</code>, this approach confines order-related data management within <code>OrderService</code>, creating a clear boundary between the two services.</p>
</li>
</ol>
<p>In practice, these service boundaries are like <strong>separate departments in a company</strong>, such as HR and Sales, where each department operates independently with its specific set of responsibilities.</p>
<p><code>UserService</code> and <code>OrderService</code> can interact with users and orders without interfering with each other, thus minimizing dependencies and enabling each service to evolve independently.</p>
<p>This design makes it easier to scale, modify, and maintain individual services without impacting other parts of the application.</p>
<h3 id="heading-decide-on-data-storage"><strong>Decide on Data Storage</strong></h3>
<p>You’ll need to choose the appropriate data storage solution for each microservice, considering factors such as scalability and consistency.</p>
<p>It’s just like choosing the right type of storage (for example, filing cabinet, cloud storage) based on what you need to store and how you need to access it.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Simple in-memory storage for demonstration</span>
<span class="hljs-keyword">const</span> userDatabase = {}; <span class="hljs-comment">// For UserService</span>
<span class="hljs-keyword">const</span> orderDatabase = {}; <span class="hljs-comment">// For OrderService</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
  createUser(user) {
    userDatabase[user.id] = user;
  }

  getUser(userId) {
    <span class="hljs-keyword">return</span> userDatabase[userId];
  }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span> </span>{
  createOrder(order) {
    orderDatabase[order.id] = order;
  }

  getOrder(orderId) {
    <span class="hljs-keyword">return</span> orderDatabase[orderId];
  }
}
</code></pre>
<p>In this code, you can see how <strong>each service is designed to operate with its own isolated storage</strong>:</p>
<ol>
<li><p><strong>UserService</strong>: The <code>UserService</code> class interacts solely with the <code>userDatabase</code> object. When the <code>createUser</code> method is called, it stores the user’s data in <code>userDatabase</code>, using the user’s ID as the key to make retrieval efficient. The <code>getUser</code> method retrieves user data by accessing this in-memory "database" with the user ID. This approach confines user data management entirely within the <code>UserService</code>, preventing other services from directly accessing or modifying it, which aligns with the microservices goal of encapsulating data within the responsible service.</p>
</li>
<li><p><strong>OrderService</strong>: Similarly, the <code>OrderService</code> class interacts only with <code>orderDatabase</code>, a separate in-memory object dedicated to storing order-related data. The <code>createOrder</code> method adds order information to this object, using each order’s unique ID as a key. The <code>getOrder</code> method then retrieves orders from <code>orderDatabase</code> as needed. As with <code>UserService</code>, <code>OrderService</code> maintains strict data separation, ensuring that order data is accessible only within the context of this service.</p>
</li>
</ol>
<p>This structure emphasizes <strong>decoupling data management for each service</strong>, which offers several advantages in a microservices architecture. For instance, by isolating each service’s data, this model allows each service to choose the most suitable data storage solution based on its specific requirements.</p>
<p>Just as an organization might choose cloud storage for accessible files and secure storage for sensitive documents, each microservice could adopt a different database type (for example, SQL, NoSQL) depending on its workload.</p>
<p>This separation also supports scalability, as each service can independently scale its storage layer without affecting others.</p>
<h3 id="heading-choose-the-right-technology-stack"><strong>Choose the Right Technology Stack</strong></h3>
<p>Selecting the appropriate technology stack is a crucial step in building microservices.</p>
<p>This decision impacts your microservices architecture's performance, scalability, maintainability, and overall success.</p>
<p>The flexibility of microservices allows you to choose different programming languages, frameworks, and tools for various services, optimizing each one for its specific needs.</p>
<h4 id="heading-programming-languages"><strong>Programming Languages</strong></h4>
<p>In a microservices architecture, you can use different programming languages for different services based on their requirements.</p>
<p>For instance, you might choose JavaScript (Node.js) for real-time services, Python for data processing, and Java for high-performance backend services.</p>
<p><strong>Here’s what to consider:</strong></p>
<ul>
<li><p><strong>Team Expertise:</strong> Choose languages your team is proficient in to reduce the learning curve and increase productivity.</p>
</li>
<li><p><strong>Ecosystem and Libraries:</strong> Consider the availability of frameworks, libraries, and community support for the language.</p>
</li>
<li><p><strong>Performance Needs:</strong> Some languages offer better performance for specific tasks. For example, Go is often chosen for its concurrency capabilities in high-performance applications.</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// Node.js example for a simple microservice</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();

app.get(<span class="hljs-string">'/hello'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.send(<span class="hljs-string">'Hello, World!'</span>);
});

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Service running on port 3000'</span>);
});
</code></pre>
<p>In the code above, you can see how a <strong>basic Node.js-based microservice</strong> works by using the Express framework to handle a simple HTTP GET request.</p>
<p>This example demonstrates setting up a microservice with minimal code, illustrating how microservices can efficiently serve specific functionalities.</p>
<p>In this code, you can see:</p>
<ol>
<li><p><strong>Express Setup</strong>: The code starts by importing the <code>express</code> module, which is a lightweight, flexible Node.js framework commonly used for building microservices and web applications. <code>express()</code> initializes an application instance named <code>app</code>, allowing us to define routes and behaviors.</p>
</li>
<li><p><strong>Defining a Route</strong>: Next, we define a route handler using <code>app.get('/hello', (req, res) =&gt; { ... })</code>. This line sets up an endpoint, <code>/hello</code>, which will respond to HTTP GET requests. When a request is made to this endpoint, the callback function sends back a response of <code>"Hello, World!"</code>. This function demonstrates how specific endpoints can be easily created within a microservice to handle different requests and responses.</p>
</li>
<li><p><strong>Starting the Server</strong>: The line <code>app.listen(3000, ...)</code> instructs the app to listen on port 3000, meaning it will respond to incoming requests on this port. When the server successfully starts, a message, <code>"Service running on port 3000"</code>, is logged to the console. This line is crucial for making the microservice operational, as it opens up the specified port for client communication.</p>
</li>
</ol>
<p>This setup is a typical approach for a simple microservice, where each microservice can run independently, serve specific routes, and perform unique actions.</p>
<p>It demonstrates the concept of <strong>service boundaries</strong> by limiting the functionality of this microservice to a specific purpose: handling requests to the <code>/hello</code> endpoint and responding with a message.</p>
<p>This design can be expanded by adding more endpoints, handling more request types, and incorporating additional logic as needed.</p>
<h4 id="heading-frameworks"><strong>Frameworks</strong></h4>
<p>Depending on the complexity and requirements of your service, you might choose a lightweight framework (like Express.js for Node.js) or a more comprehensive one (like Spring Boot for Java).</p>
<p>Some frameworks are specifically designed for microservices, offering built-in support for service discovery, configuration management, and other essential features. Examples include Spring Boot (Java) and Micronaut (Java, Groovy, Kotlin).</p>
<p><strong>Here’s what to consider:</strong></p>
<ul>
<li><p><strong>Scalability:</strong> Ensure the framework supports horizontal scaling and distributed systems.</p>
</li>
<li><p><strong>Ease of Integration:</strong> Choose frameworks that integrate well with your existing systems and technologies.</p>
</li>
<li><p><strong>Developer Productivity:</strong> Frameworks with higher levels of abstraction can speed up development but may also limit flexibility.</p>
</li>
</ul>
<pre><code class="lang-java"><span class="hljs-comment">// Spring Boot example for a simple microservice</span>
<span class="hljs-meta">@RestController</span>
<span class="hljs-meta">@RequestMapping("/api")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloWorldController</span> </span>{

    <span class="hljs-meta">@GetMapping("/hello")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">hello</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Hello, World!"</span>;
    }
}
</code></pre>
<p>This code illustrates how a simple Spring Boot microservice works, specifically by defining a REST endpoint that responds to HTTP requests.</p>
<ul>
<li><p>You have a <code>HelloWorldController</code> class, annotated with <code>@RestController</code>, which marks it as a RESTful web service controller in Spring Boot. This annotation allows the class to handle incoming HTTP requests and automatically converts responses into JSON, making it ideal for building microservices.</p>
</li>
<li><p>The <code>@RequestMapping("/api")</code> annotation specifies a base URI for all endpoints in this controller. In this case, all routes managed by <code>HelloWorldController</code> will begin with <code>/api</code>, organizing the API endpoints under a single base path.</p>
</li>
<li><p>Within the class, the <code>@GetMapping("/hello")</code> annotation is used on the <code>hello()</code> method, designating it as an HTTP <code>GET</code> endpoint. This means that whenever the <code>/api/hello</code> route is accessed with a <code>GET</code> request, the <code>hello()</code> method will be triggered.</p>
</li>
<li><p>The <code>hello()</code> method is a simple function that returns the string <code>"Hello, World!"</code>. When a client makes a request to <code>/api/hello</code>, Spring Boot processes this request and sends back the <code>"Hello, World!"</code> response, formatted according to HTTP standards.</p>
</li>
</ul>
<p>This setup forms the basis of a simple microservice endpoint, as it defines a clear URI path, method type, and response format, encapsulated within a RESTful API.</p>
<p>The example provided explains how Spring Boot's annotations streamline the development process for RESTful services. The <code>@RestController</code> and route-mapping annotations handle much of the boilerplate, allowing developers to focus on building individual endpoints.</p>
<p>This simplicity is especially beneficial in microservices architecture, where small, single-purpose services can be rapidly developed, tested, and scaled independently.</p>
<h4 id="heading-technology-stack-alignment"><strong>Technology Stack Alignment</strong></h4>
<p>While microservices allow for different stacks across services, it’s important to strike a balance between consistency (to avoid operational overhead) and flexibility (to optimize individual services). For example, you might standardize certain tools for monitoring, logging, and CI/CD, even if you use different languages.</p>
<p>You should also consider how your chosen technology stack works within containers (like Docker). Containerization enables consistent environments across development, testing, and production.</p>
<h3 id="heading-defining-apis-and-contracts"><strong>Defining APIs and Contracts</strong></h3>
<p>Defining clear and well-structured APIs is a cornerstone of successful microservices architecture.</p>
<p>APIs serve as the communication bridge between microservices, enabling them to work together while remaining loosely coupled.</p>
<h4 id="heading-api-design-principles-restful-vs-grpc"><strong>API Design Principles: RESTful vs. gRPC</strong></h4>
<p><strong>RESTful APIs:</strong> REST (Representational State Transfer) is widely used due to its simplicity, human-readability, and ease of integration with HTTP. RESTful APIs are typically designed around resources and use standard HTTP methods (GET, POST, PUT, DELETE).</p>
<pre><code class="lang-http"><span class="hljs-attribute">GET /api/users/{id}</span>
</code></pre>
<p>In this HTTP code, you can see how a <strong>RESTful API request</strong> is structured to retrieve user information by ID. This endpoint, represented by <code>GET /api/users/{id}</code>, is a commonly used RESTful pattern for accessing specific resources, in this case, user data.</p>
<p>Here’s a breakdown of what this endpoint does and how it works:</p>
<ol>
<li><p>The <code>GET</code> method is used to request data from the server, and it’s specifically designed to retrieve information without modifying any data on the server. In this context, the <code>GET</code> request is directed to the <code>/api/users/{id}</code> endpoint, where <code>{id}</code> represents a variable placeholder for the specific user’s unique identifier.</p>
</li>
<li><p>When a request is made to this endpoint (for example, <code>GET /api/users/123</code>), the server interprets <code>{id}</code> as the ID of the user whose data is being requested.</p>
</li>
<li><p>The server then retrieves the relevant user information from its database and sends it back to the client, typically in JSON format.</p>
</li>
</ol>
<p>This approach aligns with the principles of REST (Representational State Transfer), which emphasizes stateless communication and the use of standard HTTP methods (like GET, POST, PUT, DELETE) to interact with resources.</p>
<p>By separating the endpoint path (<code>/api/users</code>) and the method (<code>GET</code>), this design provides a clear, intuitive interface for retrieving data, making it easy for clients to understand that this request will fetch user information based on the unique user ID provided.</p>
<p>Using specific paths with parameters like <code>{id}</code> keeps the API flexible, allowing clients to dynamically request data for any user by substituting the appropriate ID in the request URL.</p>
<p>This is especially useful in microservice or RESTful architectures, where clear, predictable endpoints improve communication efficiency and maintain data access consistency across distributed services.</p>
<p><strong>gRPC:</strong> gRPC is a high-performance, open-source RPC (Remote Procedure Call) framework developed by Google. It uses HTTP/2 and Protocol Buffers for efficient communication, making it suitable for low-latency, high-throughput systems.</p>
<pre><code class="lang-plaintext">service UserService {
    rpc GetUser (UserRequest) returns (UserResponse);
}
</code></pre>
<p>In this code, you can see how <strong>gRPC service definitions</strong> are created to specify the RPC (Remote Procedure Call) interface for the <code>UserService</code>.</p>
<p>This example uses Protocol Buffers (protobuf) syntax, a language-neutral format for defining service contracts in gRPC.</p>
<p>Here’s a detailed breakdown of how this code works and what it represents:</p>
<ol>
<li><p>The <code>service UserService</code> declaration defines a service named <code>UserService</code>. In gRPC, a "service" is essentially a collection of remotely callable functions. It organizes these functions (or RPC methods) under a single service name, which can be easily referenced by clients wishing to interact with it.</p>
</li>
<li><p>Inside <code>UserService</code>, the line <code>rpc GetUser (UserRequest) returns (UserResponse);</code> defines a specific RPC method called <code>GetUser</code>. The keyword <code>rpc</code> indicates that this function will be accessible remotely via gRPC calls. The name <code>GetUser</code> indicates its purpose—to retrieve user information—and helps to standardize the naming of this action.</p>
</li>
<li><p>The <code>GetUser</code> method specifies two important details: the request and response types, represented here as <code>(UserRequest)</code> and <code>(UserResponse)</code>. <code>UserRequest</code> is the type of data the client must send when calling <code>GetUser</code>, which could include user identifiers (like a user ID) or any necessary parameters. <code>UserResponse</code> defines the format of the data that will be returned by the server, such as the user’s profile or account details.</p>
</li>
</ol>
<p>When a client makes a call to <code>GetUser</code>, they send a <code>UserRequest</code> message, and the server responds with a <code>UserResponse</code> message.</p>
<p>This structure allows for a well-defined and efficient way for clients to retrieve user information without dealing with the details of network communication.</p>
<p>By defining service contracts at this level, gRPC enables type safety, performance optimization, and scalability across distributed systems.</p>
<p><strong>Choosing Between REST and gRPC:</strong> REST is more flexible and easier to use for external APIs, while gRPC offers better performance and is often preferred for internal microservices communication.</p>
<h3 id="heading-versioning"><strong>Versioning</strong></h3>
<p>APIs evolve over time, and maintaining backward compatibility is crucial. API versioning strategies include path versioning (for example, <code>/v1/users</code>) and query parameter versioning (for example, <code>/users?version=1</code>).</p>
<pre><code class="lang-http"><span class="hljs-attribute">GET /api/v1/users/123</span>
</code></pre>
<p>In the HTTP code above, you can see how a <strong>RESTful API endpoint</strong> is defined to retrieve a resource, specifically a user, using the HTTP <code>GET</code> method.</p>
<p>This is a simple and effective way to interact with web services over HTTP, which is the backbone of REST (Representational State Transfer) design.</p>
<p>RESTful APIs are structured around the concept of resources—objects or data that can be accessed or manipulated via standard HTTP methods like <code>GET</code>, <code>POST</code>, <code>PUT</code>, and <code>DELETE</code>.</p>
<p>The endpoint <code>GET /api/users/{id}</code> follows this design pattern. Here's how it works in detail:</p>
<ul>
<li><p><code>GET</code> is the HTTP method used to request data from the server. In RESTful design, the <code>GET</code> method is used for <strong>retrieving data</strong> from a server without making any changes. In this case, the <code>GET</code> request is specifically used to fetch the details of a user.</p>
</li>
<li><p><code>/api/users/{id}</code> is the <strong>resource path</strong> that identifies the target resource—in this case, a user. The <code>{id}</code> part is a <strong>variable path parameter</strong>, which means the client must provide a specific user identifier (ID) when making the request. This allows the server to understand which user's data is being requested. For example, <code>GET /api/users/123</code> would fetch the user with the ID of <code>123</code>.</p>
</li>
<li><p>The resource, in this case, is a <strong>user</strong>. RESTful APIs focus on representing data in the form of resources, which are typically accessed using URLs. The <code>GET</code> method on the <code>/users/{id}</code> path tells the server to return the data associated with the user corresponding to the given ID.</p>
</li>
</ul>
<p>In RESTful design, the simplicity and human-readability of the HTTP protocol make it easy to integrate with other systems. Each endpoint can be understood in terms of standard HTTP methods and the structure of the resource being accessed, which makes it intuitive for both developers and clients.</p>
<p>The resource-oriented approach is scalable, and by using HTTP status codes, developers can communicate the results of each request (such as <code>200 OK</code> for success or <code>404 Not Found</code> when the resource doesn’t exist).</p>
<p>Thus, <code>GET /api/users/{id}</code> is an example of how RESTful APIs allow clients to easily query specific resources with clear, readable paths and standard methods for interaction.</p>
<h3 id="heading-error-handling"><strong>Error Handling</strong></h3>
<p>You’ll need to define a consistent approach to handling errors in your APIs. Use standardized error codes and messages to make troubleshooting easier for clients.</p>
<pre><code class="lang-json">{
    <span class="hljs-attr">"error"</span>: {
        <span class="hljs-attr">"code"</span>: <span class="hljs-string">"USER_NOT_FOUND"</span>,
        <span class="hljs-attr">"message"</span>: <span class="hljs-string">"The user with ID 123 was not found."</span>
    }
}
</code></pre>
<p>In this code, you can see how <strong>error handling</strong> works within an API response by providing standardized error information.</p>
<p>The JSON object returned represents an error response when a client attempts to access a resource, such as a user, that cannot be found.</p>
<p>The structure of the error is consistent, making it easier for both the server and client to handle errors effectively.</p>
<p>The outer structure of the response is an object containing an <code>error</code> key, which signifies that this is an error response, as opposed to a successful one. This helps clients easily distinguish between regular data responses and error responses.</p>
<p>Inside the <code>error</code> object, there are two key elements:</p>
<ul>
<li><p><code>code</code>: The error code (<code>USER_NOT_FOUND</code>) is a <strong>standardized identifier</strong> that describes the type of error. It helps developers and clients understand exactly what went wrong. In this case, <code>USER_NOT_FOUND</code> indicates that the user could not be found in the system based on the provided identifier (<code>ID 123</code>).</p>
</li>
<li><p><code>message</code>: The error message (<code>The user with ID 123 was not found.</code>) provides a <strong>human-readable explanation</strong> of the error. This message offers clarity to the user or developer about the nature of the problem, giving a more detailed description of what happened. In this case, it explicitly informs the client that the requested user is missing from the database.</p>
</li>
</ul>
<p>By using this approach, the error response is <strong>consistent</strong>, and clients can easily handle errors in a standardized way.</p>
<p>This might involve logging the error, displaying the message to the user, or retrying the operation if necessary.</p>
<p>The standardized error codes and messages make troubleshooting and debugging easier, as developers and clients can quickly identify the nature of the issue.</p>
<p>Moreover, this structure can be extended with additional information, such as timestamps or stack traces, to provide even more context if needed.</p>
<p>This consistent method for error handling ensures that both the client and server maintain clear communication, allowing developers to create more reliable and user-friendly APIs.</p>
<p>When errors are returned in a consistent and structured format like this, it also promotes better integration between different services or teams that might consume the API.</p>
<h3 id="heading-api-contracts"><strong>API Contracts</strong></h3>
<h4 id="heading-contracts-as-agreements"><strong>Contracts as Agreements</strong></h4>
<p>An API contract defines the rules for how services interact, specifying the expected inputs, outputs, and behavior. It serves as an agreement between teams, ensuring that changes in one service do not break others.</p>
<h4 id="heading-schema-definition"><strong>Schema Definition</strong></h4>
<p>Use schema definition tools like OpenAPI (formerly Swagger) or Protocol Buffers (for gRPC) to formally define your API contracts. These tools allow for the automatic generation of client libraries, documentation, and testing tools.</p>
<pre><code class="lang-yaml"><span class="hljs-attr">openapi:</span> <span class="hljs-number">3.0</span><span class="hljs-number">.0</span>
<span class="hljs-attr">info:</span>
  <span class="hljs-attr">title:</span> <span class="hljs-string">User</span> <span class="hljs-string">API</span>
  <span class="hljs-attr">version:</span> <span class="hljs-number">1.0</span><span class="hljs-number">.0</span>
<span class="hljs-attr">paths:</span>
  <span class="hljs-string">/users/{id}:</span>
    <span class="hljs-attr">get:</span>
      <span class="hljs-attr">summary:</span> <span class="hljs-string">Get</span> <span class="hljs-string">a</span> <span class="hljs-string">user</span> <span class="hljs-string">by</span> <span class="hljs-string">ID</span>
      <span class="hljs-attr">parameters:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">id</span>
          <span class="hljs-attr">in:</span> <span class="hljs-string">path</span>
          <span class="hljs-attr">required:</span> <span class="hljs-literal">true</span>
          <span class="hljs-attr">schema:</span>
            <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
      <span class="hljs-attr">responses:</span>
        <span class="hljs-attr">'200':</span>
          <span class="hljs-attr">description:</span> <span class="hljs-string">Successful</span> <span class="hljs-string">response</span>
          <span class="hljs-attr">content:</span>
            <span class="hljs-attr">application/json:</span>
              <span class="hljs-attr">schema:</span>
                <span class="hljs-string">$ref:</span> <span class="hljs-string">'#/components/schemas/User'</span>
<span class="hljs-attr">components:</span>
  <span class="hljs-attr">schemas:</span>
    <span class="hljs-attr">User:</span>
      <span class="hljs-attr">type:</span> <span class="hljs-string">object</span>
      <span class="hljs-attr">properties:</span>
        <span class="hljs-attr">id:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
        <span class="hljs-attr">name:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
        <span class="hljs-attr">email:</span>
          <span class="hljs-attr">type:</span> <span class="hljs-string">string</span>
</code></pre>
<p>In this code, you can see how <strong>OpenAPI schema definition</strong> works by specifying a formal structure for a REST API endpoint.</p>
<p>This YAML example uses OpenAPI 3.0 to define the structure and behavior of an endpoint that retrieves a user by their ID.</p>
<p>OpenAPI, formerly known as Swagger, is a popular tool for defining API contracts, which are essentially agreements about how API requests and responses should look.</p>
<p>This helps create consistency, enables the automatic generation of client libraries, documentation, and testing tools, and makes integration smoother for clients who interact with the API.</p>
<p>The <code>openapi: 3.0.0</code> line specifies the OpenAPI version, ensuring compatibility with OpenAPI 3.0 tools.</p>
<p>Under <code>info</code>, details about the API itself are defined, including the title (<code>User API</code>) and version (<code>1.0.0</code>), helping clients and developers understand what API version they are working with.</p>
<p>The <code>paths</code> section details the available endpoints, with <code>/users/{id}</code> representing a path to retrieve a user by their unique identifier.</p>
<p>The <code>get</code> section describes the specifics of this GET request, including:</p>
<ul>
<li><p>The <code>summary</code> field (<code>Get a user by ID</code>), which briefly explains the purpose of this endpoint.</p>
</li>
<li><p>The <code>parameters</code> list specifies that this endpoint accepts a single parameter, <code>id</code>, which is required, will appear in the path (<code>in: path</code>), and must be of type <code>string</code>.</p>
</li>
</ul>
<p>The <code>responses</code> section specifies possible responses:</p>
<ul>
<li><p>A <code>200</code> status indicates a successful retrieval of the user data.</p>
</li>
<li><p>Under <code>content</code>, the schema of the JSON response is defined, referencing a reusable <code>User</code> schema from the <code>components</code> section.</p>
</li>
</ul>
<p>In the <code>components</code> section, a <code>User</code> schema is defined to outline the structure of the user data returned by this API. The <code>User</code> schema is defined as an object with <code>id</code>, <code>name</code>, and <code>email</code> properties, each with specific types (<code>string</code>), detailing the expected structure of the user data.</p>
<p>This formal schema helps API clients understand exactly how to use the endpoint and what kind of data they will receive in response.</p>
<p>By defining the API in OpenAPI, this schema also enables automated documentation tools to generate visual documentation for developers. It also allows client libraries to be automatically generated to interact with the API, reducing errors and improving efficiency.</p>
<p>This example showcases how OpenAPI enables clear, consistent, and reusable API contracts that facilitate easier integration and maintenance.</p>
<h3 id="heading-api-gateways-and-security"><strong>API Gateways and Security</strong></h3>
<p>Implementing an API gateway allows you to manage cross-cutting concerns such as authentication, rate limiting, logging, and request routing. It acts as a single entry point for clients accessing microservices.</p>
<p>Security is also an important concern. You can secure your APIs using authentication mechanisms like OAuth2, API keys, or JWT (JSON Web Tokens). Also, ensure that sensitive data is encrypted both in transit and at rest.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example of securing a route in Express.js</span>
<span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);

app.get(<span class="hljs-string">'/api/secure-data'</span>, authenticateToken, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    res.json({ <span class="hljs-attr">data</span>: <span class="hljs-string">'This is secured data'</span> });
});

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">authenticateToken</span>(<span class="hljs-params">req, res, next</span>) </span>{
    <span class="hljs-keyword">const</span> token = req.headers[<span class="hljs-string">'authorization'</span>];
    <span class="hljs-keyword">if</span> (!token) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">401</span>);

    jwt.verify(token, process.env.ACCESS_TOKEN_SECRET, <span class="hljs-function">(<span class="hljs-params">err, user</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (err) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">403</span>);
        req.user = user;
        next();
    });
}
</code></pre>
<p>Here, the code illustrates how <strong>route security and authentication</strong> are implemented in an Express.js application using <strong>JSON Web Tokens (JWT)</strong>, which are a common method of securing API endpoints.</p>
<p>Here, the route <code>'/api/secure-data'</code> is configured to be accessible only to authenticated users, managed by the middleware function <code>authenticateToken</code>.</p>
<p>In the <code>authenticateToken</code> function, the code extracts the token from the request headers (<code>req.headers['authorization']</code>).</p>
<p>If no token is present, it sends a <code>401 Unauthorized</code> status, indicating that access is denied. This check is crucial for restricting access to sensitive endpoints, ensuring that only requests with a valid authorization token proceed.</p>
<p>Next, the code uses the <code>jwt.verify()</code> function to verify the token against a secret key (<code>process.env.ACCESS_TOKEN_SECRET</code>). This secret is known only to the server, which makes it possible to authenticate the validity of the token. If the token is invalid or expired, <code>jwt.verify</code> will throw an error, and the function will return a <code>403 Forbidden</code> response, blocking access.</p>
<p>When verification succeeds, the decoded user information from the token is attached to the <code>req</code> object (<code>req.user = user</code>), enabling subsequent middleware or route handlers to access user-specific data.</p>
<p>The <code>next()</code> function then passes control to the actual route handler, which, in this case, sends back a JSON object with secured data (<code>res.json({ data: 'This is secured data' })</code>).</p>
<p>This approach is often part of a larger API gateway or security strategy, as it ensures that sensitive routes can only be accessed by authenticated clients.</p>
<p>It aligns with secure API gateway practices by enforcing token-based authentication at the gateway level, enhancing security without needing to modify each microservice individually.</p>
<h2 id="heading-how-to-implement-microservices"><strong>How to Implement Microservices</strong></h2>
<p>In this chapter, we will begin applying the concepts we discussed earlier as we go through the practical steps. We’ll dive into building a sample project to demonstrate the core aspects of microservices architecture. By focusing on a simple use case, we will walk through how to develop and deploy microservices that are loosely coupled, independently deployable, and scalable.</p>
<p>The scenario we will cover involves developing a microservice system for an e-commerce platform, where we will focus on creating RESTful APIs. These APIs will allow different services, such as product catalog, user management, and order processing, to interact seamlessly while maintaining independence.</p>
<p>You will learn how to design each service with clear boundaries, handle communication between them, and ensure that the services remain decoupled yet cohesive.</p>
<p>We’ll cover topics like designing and implementing RESTful APIs, integrating services via HTTP or message queues, and introducing important concepts such as service discovery and API gateways. Each subsection will build on the previous one, so by the end of the chapter, you’ll have a solid understanding of how to create and deploy a functioning microservices application, ready for further expansion and integration.</p>
<h3 id="heading-creating-restful-apis"><strong>Creating RESTful APIs</strong></h3>
<p>You’ll implement APIs that follow REST principles to allow communication between services.</p>
<p>Think of RESTful APIs as menus in a restaurant, where each menu item (API endpoint) corresponds to a specific dish (service functionality).</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Node..js with Express</span>
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();
app.use(express.json());

<span class="hljs-keyword">const</span> users = [];

app.post(<span class="hljs-string">'/users'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.body;
  users.push(user);
  res.status(<span class="hljs-number">201</span>).send(user);
});

app.get(<span class="hljs-string">'/users/:id'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = users.find(<span class="hljs-function"><span class="hljs-params">u</span> =&gt;</span> u.id === <span class="hljs-built_in">parseInt</span>(req.params.id));
  <span class="hljs-keyword">if</span> (user) {
    res.send(user);
  } <span class="hljs-keyword">else</span> {
    res.status(<span class="hljs-number">404</span>).send(<span class="hljs-string">'User not found'</span>);
  }
});

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'User service running on port 3000'</span>));
</code></pre>
<p>This code demonstrates how a <strong>simple RESTful API</strong> is implemented in Node.js using the Express framework. This API demonstrates <strong>basic CRUD (Create and Read) operations</strong> for a <code>users</code> resource, adhering to REST principles by providing endpoints that represent specific operations on the <code>users</code> data.</p>
<p>The <code>app.use(express.json());</code> line enables Express to parse incoming JSON data, allowing the server to handle <code>POST</code> requests with JSON bodies. This is essential because microservices often communicate in JSON, making it a standard format for data exchange in RESTful APIs.</p>
<p>The <code>POST /users</code> route allows clients to create a new user by sending JSON data representing the user. In the route, the <code>req.body</code> object captures this incoming data. The server then stores this data in the <code>users</code> array.</p>
<p>It responds with a status code <code>201</code> (indicating resource creation) and sends back the user object to confirm the successful addition. This design aligns with REST principles by using a standard HTTP method (<code>POST</code>) for creating resources and returning meaningful HTTP status codes.</p>
<p>The <code>GET /users/:id</code> route allows clients to retrieve a specific user by their <code>id</code>. This endpoint uses <code>req.params.id</code> to access the <code>id</code> parameter provided in the request URL.</p>
<p>The code searches the <code>users</code> array for a matching user, converts the <code>id</code> to an integer (since it’s stored as a string in the URL), and sends back the user data if found.</p>
<p>If no match is found, the server responds with a <code>404</code> status code, indicating that the user was not found. This standard error handling approach makes the API client-friendly by providing clear feedback.</p>
<p>The final part, <code>app.listen(3000)</code>, starts the server on port 3000 and logs a message to confirm the service is running. This allows other services or clients to access the API by making HTTP requests to this port.</p>
<p>This code exemplifies a RESTful approach to creating a simple, stateless API for managing users in a microservice, with endpoints that map intuitively to create and read operations on a user resource.</p>
<h3 id="heading-handling-authentication-and-authorization"><strong>Handling Authentication and Authorization</strong></h3>
<p>You’ll want to implement mechanisms to secure access to your microservices.</p>
<p>This is like issuing badges to employees to ensure only authorized personnel can enter specific areas of a building.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Using JWT for Authentication</span>
<span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);
<span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();
app.use(express.json());

<span class="hljs-comment">// Generate JWT Token</span>
app.post(<span class="hljs-string">'/login'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> user = req.body; <span class="hljs-comment">// Assume user validation here</span>
  <span class="hljs-keyword">const</span> token = jwt.sign({ <span class="hljs-attr">userId</span>: user.id }, <span class="hljs-string">'secret_key'</span>);
  res.send({ token });
});

<span class="hljs-comment">// Middleware to protect routes</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">authenticateToken</span>(<span class="hljs-params">req, res, next</span>) </span>{
  <span class="hljs-keyword">const</span> token = req.headers[<span class="hljs-string">'authorization'</span>];
  <span class="hljs-keyword">if</span> (!token) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">401</span>);
  jwt.verify(token, <span class="hljs-string">'secret_key'</span>, <span class="hljs-function">(<span class="hljs-params">err, user</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (err) <span class="hljs-keyword">return</span> res.sendStatus(<span class="hljs-number">403</span>);
    req.user = user;
    next();
  });
}

app.get(<span class="hljs-string">'/protected'</span>, authenticateToken, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
  res.send(<span class="hljs-string">'This is a protected route'</span>);
});

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Authentication service running on port 3000'</span>));
</code></pre>
<p>In this snippet, you can see that JWT (JSON Web Tokens) are used to handle <strong>authentication and authorization</strong> in a Node.js application. The code demonstrates the entire flow, from generating a JWT token when a user logs in, to using that token to protect specific routes in the application.</p>
<p>First, in the <code>POST /login</code> route, the application generates a JWT token for a user. Here, the user’s information is expected to be provided in <code>req.body</code>, simulating a login process. In a real-world scenario, this step would include user validation (such as checking the username and password against a database).</p>
<p>Upon a successful "login," the <code>jwt.sign()</code> method creates a token using the <a target="_blank" href="http://user.id"><code>user.id</code></a> as the payload and a <code>secret_key</code>. This token is returned to the user and serves as a kind of "badge" that represents their identity and access rights. The client can store this token and send it with future requests to authenticate themselves.</p>
<p>The <code>authenticateToken</code> middleware function demonstrates how the server can validate this token on protected routes. When a request is made to a secured route, the middleware checks for a token in the <code>Authorization</code> header (<code>req.headers['authorization']</code>).</p>
<p>If no token is found, the server responds with a <code>401 Unauthorized</code> status, indicating that the client has not authenticated. If a token is present, the <code>jwt.verify()</code> method checks its validity using the same <code>secret_key</code> that was used to create it.</p>
<p>If the token is invalid (for example, expired or tampered with), the server sends a <code>403 Forbidden</code> status. If the token is valid, the middleware adds the <code>user</code> information to <code>req.user</code> and calls <code>next()</code> to allow the request to proceed to the protected route.</p>
<p>The protected route <code>GET /protected</code> demonstrates the benefit of using JWT for securing routes. Only requests containing a valid token can reach this route, providing controlled access to sensitive parts of the application.</p>
<p>This approach centralizes the responsibility for verifying the token, streamlining authentication across different services if used in a microservices context. It allows other services to quickly verify user access by using the token without needing to query a central user database on each request, a critical efficiency in distributed systems.</p>
<p>By including this kind of token-based authentication, developers create a more secure and efficient system for controlling access within their microservices architecture.</p>
<h3 id="heading-api-gateway-pattern"><strong>API Gateway Pattern</strong></h3>
<p>The API Gateway pattern is a crucial design pattern in microservices architecture.<br>It acts as an entry point for all client requests, routing them to the appropriate microservices. The API Gateway abstracts the underlying complexity of microservices, providing a unified interface for clients to interact with.</p>
<p>Think of the API Gateway as a receptionist in a large office building.<br>The receptionist directs visitors to the appropriate office based on their needs, ensuring they don’t have to navigate the entire building on their own.</p>
<h4 id="heading-responsibilities-of-an-api-gateway"><strong>Responsibilities of an API Gateway</strong></h4>
<ul>
<li><p><strong>Request Routing:</strong> The gateway directs incoming requests to the appropriate microservice based on the request's endpoint.</p>
</li>
<li><p><strong>Authentication and Authorization:</strong> It handles authentication, ensuring that only authorized users can access specific services.</p>
</li>
<li><p><strong>Rate Limiting:</strong> The gateway can limit the number of requests a client can make in a given time to prevent abuse.</p>
</li>
<li><p><strong>Load Balancing:</strong> It can distribute incoming requests across multiple instances of a service to ensure a balanced load and high availability.</p>
</li>
<li><p><strong>Caching:</strong> The gateway can cache responses from services to reduce load and improve response times for frequently requested data.</p>
</li>
<li><p><strong>Protocol Translation:</strong> It can translate between different protocols (e.g., HTTP to WebSocket) to enable communication between services using different protocols.</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();

app.use(<span class="hljs-string">'/users'</span>, <span class="hljs-function">(<span class="hljs-params">req, res</span>) =&gt;</span> {
    <span class="hljs-comment">// Forward the request to the user service</span>
    <span class="hljs-keyword">const</span> userServiceUrl = <span class="hljs-string">'http://user-service:3001'</span>;
    <span class="hljs-comment">// Example: proxy the request to the user service</span>
    req.pipe(request({ <span class="hljs-attr">url</span>: userServiceUrl + req.url })).pipe(res);
});

app.listen(<span class="hljs-number">3000</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'API Gateway running on port 3000'</span>);
});
</code></pre>
<p>Here, you can see how an API Gateway is set up in Node.js using Express to act as an entry point for all client requests, routing them to the appropriate microservice—in this case, a user service.</p>
<p>The API Gateway abstracts the complexity of microservices architecture by providing a single unified interface, ensuring that clients do not have to know about or navigate the underlying service endpoints directly.</p>
<p>The code begins by setting up an Express application, which represents the gateway service. The route <code>'/users'</code> is defined to handle requests to the user service. When a request is made to this route, the code dynamically forwards (or "proxies") the request to the designated URL of the user service, which in this example is <a target="_blank" href="http://user-service:3001"><code>http://user-service:3001</code></a>.</p>
<p>The <code>req.pipe(request({ url: userServiceUrl + req.url })).pipe(res);</code> line forwards the client's request to the user service's endpoint, waits for the response, and then sends it back to the client.</p>
<p>This forwarding mechanism uses streams (<code>req.pipe</code> and <code>.pipe(res)</code>) to efficiently pass data between the client and the user service, enabling the API Gateway to seamlessly route requests and responses without needing to manually handle each request component.</p>
<p>In this setup, the API Gateway could also potentially handle other responsibilities like authentication, rate limiting, caching, or load balancing by adding relevant middleware before or after forwarding the request to the user service.</p>
<p>By centralizing these responsibilities in the gateway, developers can ensure consistency and simplify configuration across microservices. Furthermore, this design is highly flexible: the API Gateway could be extended to route requests to other services (e.g., order, payment) as the architecture grows, without exposing the direct endpoints of these services to the client.</p>
<p>This way, the API Gateway efficiently manages communication between clients and the underlying microservices, while also allowing for streamlined security and protocol management across the system.</p>
<h6 id="heading-advantages-of-api-gateway"><strong>Advantages of API Gateway:</strong></h6>
<ul>
<li><p>Simplifies client interactions by providing a single entry point.</p>
</li>
<li><p>Centralizes cross-cutting concerns like security, logging, and monitoring.</p>
</li>
<li><p>Improves security by hiding the internal architecture of microservices from external clients.</p>
</li>
</ul>
<h6 id="heading-challenges-of-api-gateway"><strong>Challenges of API Gateway</strong></h6>
<ul>
<li><p>The API Gateway can become a bottleneck if not properly scaled.</p>
</li>
<li><p>It introduces additional latency due to the extra network hop.</p>
</li>
<li><p>Complexity in managing and configuring the gateway increases as the number of services grows.</p>
</li>
</ul>
<h3 id="heading-strangler-fig-pattern"><strong>Strangler Fig Pattern</strong></h3>
<p>The Strangler Fig pattern is a strategy for gradually replacing a legacy monolithic application with a new microservices-based architecture. The pattern is named after the strangler fig tree, which grows around and eventually replaces its host tree.</p>
<p>Imagine a vine slowly growing around a tree. Over time, the vine strengthens and eventually replaces the tree. Similarly, the new microservices gradually replace the old monolithic system until the legacy application is completely phased out.</p>
<h4 id="heading-steps-to-implement-strangler-fig"><strong>Steps to Implement Strangler Fig:</strong></h4>
<ul>
<li><p><strong>Identify Components:</strong> Begin by identifying the components of the monolithic application that can be isolated and replaced by microservices.</p>
</li>
<li><p><strong>Build and Deploy New Services:</strong> Develop microservices that replicate the functionality of the identified components.</p>
</li>
<li><p><strong>Route Traffic:</strong> Use an API Gateway or similar routing mechanism to direct relevant traffic to the new microservices while the rest of the traffic continues to flow to the monolith.</p>
</li>
<li><p><strong>Incremental Replacement:</strong> Gradually replace more components of the monolith with microservices, routing traffic accordingly until the entire monolithic application is replaced.</p>
</li>
<li><p><strong>Decommission the Monolith:</strong> Once all functionality has been transferred to microservices, the legacy system can be decommissioned.</p>
</li>
</ul>
<h4 id="heading-example-of-using-the-strangler-fig-pattern"><strong>Example of Using the Strangler Fig Pattern:</strong></h4>
<ul>
<li><p><strong>Phase 1:</strong> A monolithic e-commerce application handles product listing, user authentication, and order processing. You’d start by creating a microservice for user authentication.</p>
</li>
<li><p><strong>Phase 2:</strong> Traffic related to authentication is routed to the new microservice while the rest continues to be handled by the monolith.</p>
</li>
<li><p><strong>Phase 3:</strong> Over time, you’d add more microservices for product listing and order processing, gradually strangling the monolith until it's completely replaced.</p>
</li>
</ul>
<h6 id="heading-advantages-of-the-strangler-fig-pattern"><strong>Advantages of the Strangler Fig Pattern:</strong></h6>
<ul>
<li><p>Minimizes risk by allowing a gradual transition to microservices.</p>
</li>
<li><p>Reduces downtime and disruption since changes are made incrementally.</p>
</li>
<li><p>Allows for continuous improvement and refactoring during the transition.</p>
</li>
</ul>
<h6 id="heading-challenges-of-the-strangler-fig-pattern"><strong>Challenges of the Strangler Fig Pattern:</strong></h6>
<ul>
<li><p>Requires careful planning and coordination to avoid disrupting the existing application.</p>
</li>
<li><p>The coexistence of monolithic and microservices components can complicate deployment and operations.</p>
</li>
<li><p>Managing data consistency between the monolith and microservices during the transition can be challenging.</p>
</li>
</ul>
<h3 id="heading-backend-for-frontend-bff-pattern"><strong>Backend for Frontend (BFF) Pattern</strong></h3>
<p>The Backend for Frontend (BFF) pattern involves creating separate backend services tailored to the needs of different user interfaces or client types (for example, web, mobile, IoT).</p>
<p>Each BFF acts as a specialized API Gateway that aggregates data from various microservices and presents it in a format optimized for the specific client.</p>
<p>Imagine different versions of a product manual for various audiences—one for engineers, one for customers, and one for marketing.</p>
<p>Each version presents the same core information but is tailored to meet the specific needs and language of its audience.</p>
<h4 id="heading-steps-to-implement-the-bff-pattern">Steps to Implement the BFF Pattern:</h4>
<ul>
<li><p><strong>Client-Specific Backends:</strong> Develop a separate BFF for each client type. For example, you might have one BFF for a web application and another for a mobile app.</p>
</li>
<li><p><strong>Aggregation of Data:</strong> Each BFF aggregates and processes data from multiple microservices to provide a cohesive response to the client. This reduces the number of requests a client needs to make and tailors the response to the client’s needs.</p>
</li>
<li><p><strong>Custom Business Logic:</strong> Each BFF can include custom business logic that is specific to the client type, such as formatting data differently for mobile versus web or implementing client-specific optimizations.</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> express = <span class="hljs-built_in">require</span>(<span class="hljs-string">'express'</span>);
<span class="hljs-keyword">const</span> app = express();

<span class="hljs-comment">// BFF for mobile clients</span>
app.get(<span class="hljs-string">'/mobile/products'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">const</span> productData = <span class="hljs-keyword">await</span> fetchProductService();
    <span class="hljs-keyword">const</span> reviewData = <span class="hljs-keyword">await</span> fetchReviewService();
    res.json({ <span class="hljs-attr">products</span>: productData, <span class="hljs-attr">reviews</span>: reviewData });
});

<span class="hljs-comment">// BFF for web clients</span>
app.get(<span class="hljs-string">'/web/products'</span>, <span class="hljs-keyword">async</span> (req, res) =&gt; {
    <span class="hljs-keyword">const</span> productData = <span class="hljs-keyword">await</span> fetchProductService();
    <span class="hljs-keyword">const</span> reviewData = <span class="hljs-keyword">await</span> fetchReviewService();
    <span class="hljs-keyword">const</span> recommendationData = <span class="hljs-keyword">await</span> fetchRecommendationService();
    res.json({ <span class="hljs-attr">products</span>: productData, <span class="hljs-attr">reviews</span>: reviewData, <span class="hljs-attr">recommendations</span>: recommendationData });
});

app.listen(<span class="hljs-number">4000</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'BFF for Frontend running on port 4000'</span>);
});

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchProductService</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Logic to fetch product data</span>
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchReviewService</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Logic to fetch review data</span>
}

<span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">fetchRecommendationService</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Logic to fetch recommendation data</span>
}
</code></pre>
<p>In this implementation, you can see how the Backend for Frontend (BFF) pattern is implemented using Node.js and Express, creating tailored endpoints specifically for different types of clients (such as mobile and web).</p>
<p>The BFF pattern is useful when different clients—such as a mobile app and a web app—need to access similar but customized data from the backend. Here, the server defines two routes: <code>/mobile/products</code> for mobile clients and <code>/web/products</code> for web clients.</p>
<p>Both endpoints retrieve product and review data, but the web client’s endpoint fetches additional recommendation data to enhance the user experience with recommendations only relevant to web-based interactions.</p>
<p>In the first route, <code>app.get('/mobile/products')</code>, a request is handled by fetching product and review data through the helper functions <code>fetchProductService</code> and <code>fetchReviewService</code>, which are async functions that simulate calls to backend services or databases.</p>
<p>The results are then aggregated and sent as a single JSON response back to the mobile client, reducing the number of requests the client needs to make. This approach optimizes the experience for mobile users by delivering only essential information, which minimizes data usage and speeds up response times.</p>
<p>Similarly, in the second route, <code>app.get('/web/products')</code>, the server fetches the same product and review data but also includes recommendation data via <code>fetchRecommendationService</code>.</p>
<p>This endpoint is more tailored to the needs of a web interface, where users might benefit from additional recommendations displayed alongside product listings. This custom response aggregation, specific to each client, embodies the BFF pattern by structuring responses based on client requirements, optimizing the client-server interaction, and making backend processing more efficient.</p>
<p>The server listens on port 4000, acting as a dedicated layer for frontend communication that hides the complexity of backend services from clients.</p>
<p>By using distinct BFFs, each client’s needs are met directly through dedicated logic paths, improving efficiency, reducing overhead, and allowing each client to access precisely the data it needs in a single request.</p>
<p>This code provides a clear example of how data aggregation and client-specific tailoring can simplify and streamline API interactions in a microservices architecture.</p>
<h6 id="heading-advantages-of-the-bff-pattern"><strong>Advantages of the BFF Pattern:</strong></h6>
<ul>
<li><p>Tailors the backend services to the specific needs of each client, improving performance and user experience.</p>
</li>
<li><p>Reduces the complexity of front-end code by offloading aggregation and transformation tasks to the BFF.</p>
</li>
<li><p>Allows for independent evolution of different clients and their corresponding backends.</p>
</li>
</ul>
<h6 id="heading-challenges-of-the-bff-pattern"><strong>Challenges of the BFF Pattern:</strong></h6>
<ul>
<li><p>Increases the number of services to maintain, as each client type requires its own BFF.</p>
</li>
<li><p>Potential for code duplication if similar logic is required across multiple BFFs.</p>
</li>
<li><p>Coordination between BFFs and the underlying microservices is required to ensure consistency and efficiency.</p>
</li>
</ul>
<h2 id="heading-how-to-test-microservices"><strong>How to Test Microservices</strong></h2>
<p>Testing is an essential part of ensuring the reliability, scalability, and performance of microservices. Given that microservices are composed of multiple independent services that communicate over the network, rigorous testing becomes even more critical.</p>
<p>With each service potentially evolving independently, it’s crucial to identify and address issues early to prevent cascading failures and disruptions in the overall system. Without comprehensive testing, microservices can become prone to hidden bugs, integration issues, and performance bottlenecks.</p>
<p>In this section, we’ll explore the different types of testing that are important for microservices. Each type serves a specific purpose, from validating individual components to ensuring that the entire system works together as expected.</p>
<p>You'll learn how to apply unit testing, integration testing, contract testing, and end-to-end testing to create a robust and reliable microservice-based architecture.</p>
<p>By the end of this section, you'll understand how to approach testing in a microservices environment, enabling you to deliver high-quality applications.</p>
<h3 id="heading-unit-testing"><strong>Unit Testing</strong></h3>
<p>Testing individual components of a microservice is important to ensure that they work correctly in isolation.</p>
<p>This is like testing each part of a machine separately to ensure each part functions properly before assembling the entire machine.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Using Mocha and Chai</span>
<span class="hljs-keyword">const</span> { expect } = <span class="hljs-built_in">require</span>(<span class="hljs-string">'chai'</span>);
<span class="hljs-keyword">const</span> UserService = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./userService'</span>); <span class="hljs-comment">// Assume UserService is in another file</span>

describe(<span class="hljs-string">'UserService'</span>, <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">let</span> userService;

  beforeEach(<span class="hljs-function">() =&gt;</span> {
    userService = <span class="hljs-keyword">new</span> UserService();
  });

  it(<span class="hljs-string">'should create a user'</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-keyword">const</span> user = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'John Doe'</span> };
    userService.createUser(user);
    expect(userService.getUser(<span class="hljs-number">1</span>)).to.deep.equal(user);
  });
});
</code></pre>
<p>This code demonstrates how you can use Mocha and Chai to perform unit testing on the <code>UserService</code> class. The purpose of this test is to verify that the <code>UserService</code> class's <code>createUser</code> and <code>getUser</code> methods work as expected, ensuring that individual components of this microservice are reliable when tested in isolation.</p>
<p>This is essential for microservices, where each component must be robust to ensure that the system as a whole functions smoothly.</p>
<p>Here, the test suite begins with <code>describe('UserService', ...)</code>, which serves as a container for grouping multiple related test cases about <code>UserService</code>. Inside the suite, a new instance of <code>UserService</code> is created before each test by using the <code>beforeEach()</code> function, which resets the state of the <code>userService</code> instance, making each test independent and repeatable.</p>
<p>The actual test case, <code>it('should create a user', ...)</code>, simulates adding a user to the service. It defines a user object, <code>{ id: 1, name: 'John Doe' }</code>, which it then passes to <code>createUser</code>.</p>
<p>The <code>expect</code> assertion from Chai is used to compare the result of <code>userService.getUser(1)</code> to the expected <code>user</code> object.</p>
<p>By using <code>deep.equal</code>, the test confirms that the user retrieved by <code>getUser</code> has the same properties as the user added by <code>createUser</code>, checking both the ID and name fields.</p>
<p>This test validates that each part of <code>UserService</code> works as intended, fulfilling the principle of unit testing by ensuring components function correctly in isolation.</p>
<p>This approach is analogous to testing individual parts of a machine separately to ensure reliability before integrating them into the larger system, helping catch issues at the component level early in the development process.</p>
<h3 id="heading-integration-testing"><strong>Integration Testing</strong></h3>
<p>Integration testing involves testing the interactions between microservices to ensure that they work together correctly.</p>
<p>It’s like testing different departments in a company to ensure their workflows align and function seamlessly together.</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> request = <span class="hljs-built_in">require</span>(<span class="hljs-string">'supertest'</span>);
<span class="hljs-keyword">const</span> app = <span class="hljs-built_in">require</span>(<span class="hljs-string">'./app'</span>); <span class="hljs-comment">// Assume app is your Express application</span>

describe(<span class="hljs-string">'Integration Tests'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'should create and retrieve a user'</span>, <span class="hljs-keyword">async</span> () =&gt; {
    <span class="hljs-keyword">const</span> user = { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Jane Doe'</span> };

    <span class="hljs-comment">// Test creating a user</span>
    <span class="hljs-keyword">await</span> request(app)
      .post(<span class="hljs-string">'/users'</span>)
      .send(user)
      .expect(<span class="hljs-number">201</span>);

    <span class="hljs-comment">// Test retrieving the user</span>
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> request(app)
      .get(<span class="hljs-string">'/users/1'</span>)
      .expect(<span class="hljs-number">200</span>);

    expect(response.body).to.deep.equal(user);
  });
});
</code></pre>
<p>In this code, you can see how integration testing is performed using the Supertest library to verify interactions within the Express application. Integration testing is crucial for microservices as it checks that different components work correctly together, just as different departments in a company need to collaborate seamlessly.</p>
<p>The code defines a test suite <code>describe('Integration Tests', ...)</code>, where Supertest is used to make HTTP requests to the Express app and assert the responses. First, it tests creating a user by sending a <code>POST</code> request to <code>/users</code> with user data, <code>{ id: 1, name: 'Jane Doe' }</code>, which is expected to return a status code <code>201</code>, indicating successful creation.</p>
<p>The test then proceeds to check if this user can be retrieved by making a <code>GET</code> request to <code>/users/1</code>. This call is expected to return a <code>200</code> status, confirming that the user retrieval is functioning as expected.</p>
<p>The <code>expect</code> assertion is used here to ensure the response data (<code>response.body</code>) matches the created user data, <code>{ id: 1, name: 'Jane Doe' }</code>. This comparison validates that the app correctly processes and returns data across different endpoints, verifying that the service’s internal workflows are cohesive.</p>
<p>This approach of combining Supertest and assertions provides a reliable way to validate that the app's interconnected parts work as intended, allowing for early detection of issues that could disrupt service integrations in real-world deployments.</p>
<h3 id="heading-end-to-end-testing"><strong>End-to-End Testing</strong></h3>
<p>End-to-End testing makes sure that the entire application works from start to finish and checks that all components work together as expected.</p>
<p>It’s like running a full simulation of a business process to ensure everything from start to finish operates correctly.</p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Using Cypress</span>
describe(<span class="hljs-string">'End-to-End Test'</span>, <span class="hljs-function">() =&gt;</span> {
  it(<span class="hljs-string">'should create a user and verify its details'</span>, <span class="hljs-function">() =&gt;</span> {
    cy.request(<span class="hljs-string">'POST'</span>, <span class="hljs-string">'/users'</span>, { <span class="hljs-attr">id</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">name</span>: <span class="hljs-string">'Jack Doe'</span> })
      .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
        expect(response.status).to.eq(<span class="hljs-number">201</span>);
      });

    cy.request(<span class="hljs-string">'/users/1'</span>)
      .then(<span class="hljs-function"><span class="hljs-params">response</span> =&gt;</span> {
        expect(response.status).to.eq(<span class="hljs-number">200</span>);
        expect(response.body).to.have.property(<span class="hljs-string">'name'</span>, <span class="hljs-string">'Jack Doe'</span>);
      });
  });
});
</code></pre>
<p>This code illustrates how you can use Cypress to conduct an end-to-end test of a microservice application.</p>
<p>The test suite, named <code>describe('End-to-End Test', ...)</code>, is designed to create a user and verify its details. The <code>cy.request</code> method is used to simulate HTTP requests, interacting with the application’s endpoints as a real client would.</p>
<p>First, it sends a <code>POST</code> request to the <code>/users</code> endpoint, adding a user with <code>{ id: 1, name: 'Jack Doe' }</code>. After this request, an assertion checks that the response status is <code>201</code>, indicating the successful creation of the user resource.</p>
<p>The test then moves to the second part, where it retrieves the user with <code>cy.request('/users/1')</code>. The test verifies that the status code is <code>200</code>, meaning the user was found successfully. Also, <code>expect(response.body).</code><a target="_blank" href="http://to.have.property"><code>to.have.property</code></a><code>('name', 'Jack Doe')</code> confirms that the user’s name property matches the expected value, <code>'Jack Doe'</code>.</p>
<p>This test validates the entire flow of creating and retrieving a user in the system, ensuring that the application’s different components, such as database interactions and HTTP request handling, function cohesively.</p>
<p>Cypress is particularly effective for E2E testing because it runs these requests in a controlled environment, allowing developers to test real-world scenarios with reliable assertions. This type of testing can catch integration issues that may not appear in unit or integration tests, providing greater confidence in the system's overall stability.</p>
<h2 id="heading-how-to-deploy-microservices"><strong>How to Deploy Microservices</strong></h2>
<p>Deploying microservices efficiently is a key part of building scalable and resilient applications. As microservices are typically small, independent services, they must be deployed in a way that allows them to function together seamlessly within a larger ecosystem.</p>
<p>Unlike traditional monolithic applications, microservices require a different approach to deployment, focusing on automation, scalability, and continuous delivery. Deployment also involves dealing with challenges such as service discovery, load balancing, and ensuring fault tolerance.</p>
<p>In this section, I’ll guide you through the various strategies and tools for deploying microservices. From containerization with Docker to orchestrating services with Kubernetes, we’ll explore how these technologies simplify the deployment process.</p>
<p>We will also cover essential topics such as continuous integration/continuous deployment (CI/CD) pipelines, automated scaling, and monitoring to ensure that your microservices architecture remains robust and adaptable in production environments.</p>
<p>By the end of this section, you will have a clear understanding of how to deploy microservices efficiently and how to maintain them as your application grows.</p>
<h3 id="heading-containerization-with-docker"><strong>Containerization with Docker</strong></h3>
<p>Packaging microservices into Docker containers helps you consistently deploy across different environments.</p>
<p>It’s like using standardized shipping containers to transport goods efficiently and predictably.</p>
<pre><code class="lang-dockerfile"><span class="hljs-comment"># Dockerfile for a Node.js app</span>

<span class="hljs-comment"># Use Node.js image</span>
<span class="hljs-keyword">FROM</span> node:<span class="hljs-number">14</span>

<span class="hljs-comment"># Set working directory</span>
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /usr/src/app</span>

<span class="hljs-comment"># Copy package.json and install dependencies</span>
<span class="hljs-keyword">COPY</span><span class="bash"> package*.json ./</span>
<span class="hljs-keyword">RUN</span><span class="bash"> npm install</span>

<span class="hljs-comment"># Copy application code</span>
<span class="hljs-keyword">COPY</span><span class="bash"> . .</span>

<span class="hljs-comment"># Expose port</span>
<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">3000</span>

<span class="hljs-comment"># Run the application</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [ <span class="hljs-string">"node"</span>, <span class="hljs-string">"app.js"</span> ]</span>
</code></pre>
<p>Here, the code illustrates how you can use Docker to create a containerized environment for a Node.js application, ensuring that it can be deployed consistently across different environments.</p>
<p>Containerization with Docker works by encapsulating all the necessary application components, like code, runtime, libraries, and dependencies, into a standardized container image.</p>
<p>This approach provides predictable, repeatable deployments, similar to how standardized shipping containers are used to transport goods reliably across various transportation systems.</p>
<p>Starting with <code>FROM node:14</code>, the Dockerfile specifies a base image, in this case, an official Node.js image with version 14. This base image provides a pre-configured environment with Node.js installed, reducing the setup time and complexity required to run the app.</p>
<p>By using a standardized base, this Dockerfile also ensures compatibility and eliminates potential inconsistencies that could occur with different Node.js versions.</p>
<p>The <code>WORKDIR /usr/src/app</code> command sets the working directory inside the container to <code>/usr/src/app</code>, which organizes the application’s code files and simplifies file path references later in the Dockerfile.</p>
<p>The <code>COPY package*.json ./</code> line then copies the <code>package.json</code> files into this working directory, and <code>RUN npm install</code> installs the necessary Node.js dependencies. This process isolates the dependency installation to ensure that all required libraries are present, matching the exact versions defined in <code>package.json</code>.</p>
<p>Next, <code>COPY . .</code> copies the rest of the application files from the host system into the container’s working directory.</p>
<p>The <code>EXPOSE 3000</code> command designates port 3000 as the application’s external communication port, allowing traffic to be directed to this port when the container is run. Finally, <code>CMD ["node", "app.js"]</code> defines the container’s entry point, instructing Docker to execute <code>node app.js</code> to start the application when the container is launched.</p>
<p>This Dockerfile showcases the fundamental steps in building a Docker image for a Node.js app, enabling consistent and reproducible deployments. By following these steps, developers ensure that the application can be easily transferred between development, testing, and production environments without compatibility issues.</p>
<p>This predictable deployment approach streamlines operations, making it ideal for scaling and managing microservices in a production ecosystem.</p>
<h2 id="heading-continuous-integration-and-continuous-deployment-cicd"><strong>Continuous Integration and Continuous Deployment (CI/CD)</strong></h2>
<p>CI/CD helps you automate the process of building, testing, and deploying microservices.</p>
<p>It’s like having an automated assembly line that assembles, tests, and packages products without manual intervention.</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># Using GitHub Actions for Node.js</span>

<span class="hljs-comment"># .github/workflows/node.js.yml</span>
<span class="hljs-attr">name:</span> <span class="hljs-string">Node.js</span> <span class="hljs-string">CI</span>

<span class="hljs-attr">on:</span>
  <span class="hljs-attr">push:</span>
    <span class="hljs-attr">branches:</span> [<span class="hljs-string">main</span>]

<span class="hljs-attr">jobs:</span>
  <span class="hljs-attr">build:</span>
    <span class="hljs-attr">runs-on:</span> <span class="hljs-string">ubuntu-latest</span>

    <span class="hljs-attr">steps:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Checkout</span> <span class="hljs-string">code</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/checkout@v3</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Set</span> <span class="hljs-string">up</span> <span class="hljs-string">Node.js</span>
        <span class="hljs-attr">uses:</span> <span class="hljs-string">actions/setup-node@v3</span>
        <span class="hljs-attr">with:</span>
          <span class="hljs-attr">node-version:</span> <span class="hljs-string">'14'</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Install</span> <span class="hljs-string">dependencies</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">install</span>

      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">Run</span> <span class="hljs-string">tests</span>
        <span class="hljs-attr">run:</span> <span class="hljs-string">npm</span> <span class="hljs-string">test</span>
</code></pre>
<p>The code above shows the process of how GitHub Actions is used to automate the Continuous Integration (CI) process for a Node.js application. The CI/CD pipeline ensures that code is automatically built, tested, and prepared for deployment without manual intervention, much like an automated assembly line that assembles, tests, and packages products seamlessly.</p>
<p>The file begins with the line <code>name: Node.js CI</code>, which sets the name of the workflow. The <code>on:</code> section specifies when the workflow should be triggered. In this case, it’s set to trigger on <code>push</code> events to the <code>main</code> branch.</p>
<p>This means every time a developer pushes changes to the main branch, GitHub Actions will automatically start the pipeline to check the quality and functionality of the code.</p>
<p>The <code>jobs:</code> section defines the tasks to be executed in this pipeline, and it specifies that the job will run on <code>ubuntu-latest</code>, a virtual machine environment provided by GitHub to run the workflow. Inside the <code>build</code> job, there are several <code>steps</code> that execute sequentially.</p>
<p>In the first step, <code>Checkout code</code>, uses the <code>actions/checkout@v3</code> action to check out the repository’s code so that the subsequent steps can operate on it.</p>
<p>In the next step, <code>Set up Node.js</code>, utilizes <code>actions/setup-node@v3</code> to install Node.js version 14. This step ensures that the correct version of Node.js is used for the application, avoiding discrepancies between environments.</p>
<p>After setting up Node.js, the step <code>Install dependencies</code> runs the command <code>npm install</code>, which installs all the dependencies defined in the project’s <code>package.json</code> file. This ensures that the necessary packages are available for the tests to run.</p>
<p>Finally, the last step, <code>Run tests</code>, runs the command <code>npm test</code>, which triggers the tests for the Node.js application. This step ensures that any changes made in the code do not break the functionality of the application, as the tests will validate that everything works as expected.</p>
<p>Through this GitHub Actions configuration, the CI process is fully automated. Every time changes are pushed to the main branch, the pipeline builds the project, installs dependencies, and runs the tests.</p>
<p>This process ensures that issues are caught early, streamlining development and improving code quality by providing automated feedback on the state of the application. It also saves time by eliminating the need for manual testing and deployment steps.</p>
<h3 id="heading-orchestration-with-kubernetes"><strong>Orchestration with Kubernetes</strong></h3>
<p>Kubernetes helps you manage the deployment, scaling, and operation of containerized applications.</p>
<p>Like a conductor orchestrating a symphony, Kubernetes manages and coordinates the deployment and scaling of your containerized services.</p>
<pre><code class="lang-yaml"><span class="hljs-comment"># Kubernetes YAML for a Node.js app</span>

<span class="hljs-comment"># Deployment definition</span>
<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">user-service</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">user-service</span>
  <span class="hljs-attr">template:</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">user-service</span>
    <span class="hljs-attr">spec:</span>
      <span class="hljs-attr">containers:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">user-service</span>
          <span class="hljs-attr">image:</span> <span class="hljs-string">user-service:latest</span>
          <span class="hljs-attr">ports:</span>
            <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">3000</span>

<span class="hljs-comment"># Service definition</span>
<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Service</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">user-service</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">app:</span> <span class="hljs-string">user-service</span>
  <span class="hljs-attr">ports:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">protocol:</span> <span class="hljs-string">TCP</span>
      <span class="hljs-attr">port:</span> <span class="hljs-number">80</span>
      <span class="hljs-attr">targetPort:</span> <span class="hljs-number">3000</span>
  <span class="hljs-attr">type:</span> <span class="hljs-string">LoadBalancer</span>
</code></pre>
<p>This code illustrates how you can use Kubernetes to orchestrate the deployment and management of a Node.js application, specifically the <code>user-service</code>.</p>
<p>This YAML configuration file contains two main sections: the <strong>Deployment</strong> and the <strong>Service</strong>.</p>
<p>The <strong>Deployment</strong> section is where you define how your application should be deployed in the Kubernetes cluster. It specifies the <code>apiVersion</code>, which indicates which version of the Kubernetes API should be used to create the resource, and the <code>kind</code>, which identifies the type of resource being defined (in this case, a <code>Deployment</code>).</p>
<p>The <code>metadata</code> section contains basic information about the deployment, such as its name (<code>user-service</code>). Under <code>spec</code>, you define the desired state for the application.</p>
<p>The <code>replicas: 3</code> field indicates that Kubernetes should maintain three identical instances of the <code>user-service</code> pod running at all times, which helps ensure high availability and load balancing.</p>
<p>The <code>selector</code> field defines a label selector that is used to identify the set of pods that this deployment should manage. The <code>template</code> section defines the pod’s metadata and its spec.</p>
<p>This includes a container definition, where the <code>image</code> is set to <code>user-service:latest</code>, pointing to the Docker image to be used for the container. The <code>ports</code> section specifies that the container will listen on port 3000, which is the port your Node.js app will use.</p>
<p>In the <strong>Service</strong> section, Kubernetes defines how to expose the deployed application so that other services or external clients can access it. The <code>Service</code> is also defined with <code>apiVersion: v1</code> and <code>kind: Service</code>, indicating that it will use Kubernetes’ core service management. The <code>metadata</code> section defines the service name (<code>user-service</code>), while the <code>spec</code> section describes the service's behavior.</p>
<p>The <code>selector</code> here refers to the same label as the deployment (<code>app: user-service</code>), ensuring that the service will route traffic to the pods created by the deployment. The <code>ports</code> section specifies that the service will listen on port 80 (the external port) and forward traffic to port 3000 (the port inside the container where the app is running).</p>
<p>Finally, the <code>type: LoadBalancer</code> tells Kubernetes to provision an external load balancer, distributing incoming traffic across the multiple instances of the <code>user-service</code> pods, further ensuring high availability and fault tolerance.</p>
<p>Through this orchestration, Kubernetes ensures that your <code>user-service</code> is deployed, scaled, and exposed in a highly available manner, much like a conductor ensuring that all sections of a symphony play in time and tune.</p>
<p>It provides detailed guidance on choosing the right technology stack, defining APIs and contracts, and understanding key design patterns.</p>
<p>Selecting appropriate programming languages and frameworks is crucial for optimizing each microservice, while well-defined APIs and contracts ensure clear and reliable communication between services.</p>
<p>Key design patterns such as the API Gateway Pattern, Strangler Fig Pattern, and Backend for Frontend (BFF) Pattern are explained to help manage and optimize microservices architecture.</p>
<h2 id="heading-how-to-manage-microservices-in-the-cloud"><strong>How to Manage Microservices in the Cloud</strong></h2>
<p>This section delves into the essential practices, tools, and strategies needed to effectively operate and scale microservices in cloud environments. As more organizations migrate to the cloud, understanding the nuances of managing microservices in these dynamic settings has become crucial.</p>
<p>Here, we will look at how cloud platforms like AWS, Google Cloud, and Azure support microservices and enable seamless deployment, autoscaling, and load balancing.</p>
<p>This section also introduces key tools for orchestrating and monitoring microservices in the cloud, from Kubernetes for container orchestration to observability solutions like Prometheus and Grafana.</p>
<p>With microservices requiring intricate handling of distributed components, we’ll cover practices for maintaining service health, achieving resilience, and ensuring security across cloud-based microservices.</p>
<p>By exploring these foundational elements, readers will gain insights into managing, scaling, and optimizing microservices effectively within cloud infrastructures, equipping them with knowledge to handle real-world complexities.</p>
<h3 id="heading-cloud-platforms-and-services"><strong>Cloud Platforms and Services</strong></h3>
<h4 id="heading-1-amazon-web-services-aws"><strong>1. Amazon Web Services (AWS)</strong>:</h4>
<p>AWS offers a broad range of services tailored for microservices architecture. Some relevant services include <a target="_blank" href="https://aws.amazon.com/ecs/"><strong>Elastic Container Service (ECS)</strong></a> for container management and <a target="_blank" href="https://aws.amazon.com/eks/"><strong>Elastic Kubernetes Service (EKS)</strong></a> for orchestrating Kubernetes clusters.</p>
<p>Example: Running Node.js microservices in Docker containers managed by ECS.</p>
<h4 id="heading-2-microsoft-azure"><strong>2. Microsoft Azure</strong>:</h4>
<p>Azure provides <a target="_blank" href="https://azure.microsoft.com/en-us/products/kubernetes-service"><strong>Azure Kubernetes Service (AKS)</strong></a> for Kubernetes orchestration, <a target="_blank" href="https://azure.microsoft.com/en-us/products/service-fabric"><strong>Azure Service Fabric</strong></a> for building scalable microservices, and <a target="_blank" href="https://azure.microsoft.com/en-us/products/functions"><strong>Azure Functions</strong></a> for serverless microservices.</p>
<p>Example: Deploying an Express.js app on Azure Functions as a microservice.</p>
<h4 id="heading-3-google-cloud-platform-gcp"><strong>3. Google Cloud Platform (GCP)</strong>:</h4>
<p>GCP offers <a target="_blank" href="https://cloud.google.com/kubernetes-engine"><strong>Google Kubernetes Engine (GKE)</strong></a> for orchestrating microservices using Kubernetes and <a target="_blank" href="https://cloud.google.com/run"><strong>Cloud Run</strong></a> for running containerized apps in a fully managed environment.</p>
<p>Example: Deploying a microservice with Google Kubernetes Engine.</p>
<h3 id="heading-cloud-native-services-for-microservices"><strong>Cloud-Native Services for Microservices</strong></h3>
<p>Cloud providers offer specialized services for microservices that simplify scaling and management:</p>
<ol>
<li><p><strong>AWS ECS</strong>: Manages Docker containers on a cluster, with integration to AWS services.</p>
</li>
<li><p><strong>Google Kubernetes Engine (GKE)</strong>: Manages Kubernetes clusters with autoscaling features for microservices.</p>
</li>
</ol>
<p>Running a simple Node.js container in GCP Cloud Run:</p>
<pre><code class="lang-bash">gcloud run deploy --image gcr.io/my-project/my-node-service --platform managed
</code></pre>
<p>In this Git Bash terminal command, you can see how to deploy a containerized Node.js application using Google Cloud Run, which is a fully managed platform that automatically handles your application’s infrastructure. This allows you to focus on writing and deploying code without managing servers.</p>
<p>The <code>gcloud run deploy</code> command is used to deploy your application to Cloud Run. It tells Google Cloud to deploy an application to Cloud Run. This is the primary command for initiating the deployment process. It’s a command line tool for interacting with Google Cloud services.</p>
<p>The <code>--image</code> <a target="_blank" href="http://gcr.io/my-project/my-node-service"><code>gcr.io/my-project/my-node-service</code></a> specifies the Docker image to be deployed. This image is hosted in Google Cloud's Container Registry (GCR), indicated by <a target="_blank" href="http://gcr.io"><code>gcr.io</code></a>.</p>
<p>The <code>my-project</code> is the ID of your Google Cloud project, and <code>my-node-service</code> refers to the specific Docker image built for your Node.js application. This image contains everything that the application needs to run: the Node.js runtime, dependencies, and your application code.</p>
<p>The <code>--platform managed</code> flag tells Google Cloud Run to use the managed platform for hosting the service. Cloud Run offers both a managed and an Anthos-based platform, and by specifying <code>managed</code>, you're opting for the fully managed service where Google automatically handles things like scaling, networking, and availability.</p>
<p>This ensures that the application will automatically scale up or down based on incoming traffic, without you needing to manually configure or manage the infrastructure.</p>
<p>When you run this command, Cloud Run takes the specified Docker image, deploys it as a service, and makes it available for incoming HTTP requests. This deployment model abstracts away much of the complexity of managing the underlying infrastructure, allowing you to focus purely on application development.</p>
<p>Cloud Run automatically provisions resources, monitors the health of the service, and ensures that scaling is handled as traffic fluctuates.</p>
<p>In this setup, you can take advantage of Cloud Run’s ease of use, as it integrates well with Google Cloud’s serverless offerings, helping you run your containerized Node.js application with minimal setup or management.</p>
<h2 id="heading-containerization-and-orchestration"><strong>Containerization and Orchestration</strong></h2>
<h3 id="heading-introduction-to-containers-docker"><strong>Introduction to Containers (Docker)</strong></h3>
<p>Containers encapsulate microservices along with their dependencies, ensuring they run consistently across different environments. <a target="_blank" href="https://www.docker.com/"><strong>Docker</strong></a> is the most common containerization tool.</p>
<p>Containers are like shipping containers for software. No matter where you send them, the contents (code and dependencies) remain the same.</p>
<p><strong>Dockerfile for Node.js Microservice</strong>:</p>
<pre><code class="lang-dockerfile"><span class="hljs-comment"># Use the Node.js 16 image</span>
<span class="hljs-keyword">FROM</span> node:<span class="hljs-number">16</span>

<span class="hljs-comment"># Create app directory</span>
<span class="hljs-keyword">WORKDIR</span><span class="bash"> /usr/src/app</span>

<span class="hljs-comment"># Install dependencies</span>
<span class="hljs-keyword">COPY</span><span class="bash"> package*.json ./</span>
<span class="hljs-keyword">RUN</span><span class="bash"> npm install</span>

<span class="hljs-comment"># Copy app source code</span>
<span class="hljs-keyword">COPY</span><span class="bash"> . .</span>

<span class="hljs-comment"># Expose port and start app</span>
<span class="hljs-keyword">EXPOSE</span> <span class="hljs-number">8080</span>
<span class="hljs-keyword">CMD</span><span class="bash"> [<span class="hljs-string">"node"</span>, <span class="hljs-string">"app.js"</span>]</span>
</code></pre>
<p>In this snippet, you can see how to define a Dockerfile for a Node.js microservice, which is used to build and containerize the application for deployment. The Dockerfile provides a series of steps that Docker will follow to create an image that can be run anywhere that Docker is supported.</p>
<p>The first line, <code>FROM node:16</code>, specifies the base image to use for the container. In this case, it uses the official Node.js image with version 16.</p>
<p>By using a specific version like this, you ensure that your application runs consistently in a controlled environment with Node.js version 16, regardless of the machine or platform it is deployed to. This guarantees compatibility with the dependencies and features available in Node.js 16.</p>
<p>The <code>WORKDIR /usr/src/app</code> line sets the working directory within the container to <code>/usr/src/app</code>. This is where your application code will live inside the container. By setting the working directory explicitly, all subsequent commands like <code>COPY</code> and <code>RUN</code> will be relative to this location, helping to keep things organized within the container’s filesystem.</p>
<p>The <code>COPY package*.json ./</code> command copies the <code>package.json</code> and <code>package-lock.json</code> files (or any matching files in the pattern) into the container. This is a crucial step as these files contain the metadata and dependencies required for the Node.js application.</p>
<p>This allows Docker to install all necessary dependencies without copying the entire application code first, which takes advantage of Docker’s caching mechanism to avoid reinstalling dependencies when they haven’t changed.</p>
<p>Next, the <code>RUN npm install</code> command installs the dependencies listed in the <code>package.json</code> file. This command is run during the image-building process, meaning all the dependencies will be available when the container is started. This installation is done inside the Docker container, ensuring that the app has everything it needs to run.</p>
<p>The <code>COPY . .</code> command copies the rest of the application code into the container’s working directory. This step ensures that all the source code, such as your <code>app.js</code> file and any other necessary files, is available inside the container so that it can be executed by Node.js.</p>
<p>The <code>EXPOSE 8080</code> line tells Docker that the container will listen on port 8080. This is the port that external systems will use to communicate with the running service.</p>
<p>While the <code>EXPOSE</code> command does not directly open the port, it serves as a documentation feature and makes the port accessible when the container is run with the appropriate Docker run configuration.</p>
<p>Finally, <code>CMD ["node", "app.js"]</code> defines the default command to run when the container starts. In this case, it tells Docker to run the <code>app.js</code> file using Node.js. This is the entry point of your application, and once the container starts, Node.js will execute this file to run your application.</p>
<p>Overall, this Dockerfile is a simple and efficient way to package a Node.js microservice into a container. By specifying the environment, dependencies, and instructions on how to start the application, it ensures that the service can run in any environment where Docker is supported, with consistent behavior across development, staging, and production systems.</p>
<h3 id="heading-container-orchestration-tools-kubernetes-docker-swarm"><strong>Container Orchestration Tools (Kubernetes, Docker Swarm)</strong></h3>
<p><a target="_blank" href="https://kubernetes.io/"><strong>Kubernetes</strong></a> is the most widely used container orchestration platform, providing features like automatic scaling, load balancing, and self-healing.</p>
<p>Kubernetes is like a traffic controller, managing how containers (microservices) are deployed, scaled, and routed.</p>
<p><strong>Kubernetes (Simple Deployment YAML)</strong>:</p>
<pre><code class="lang-yaml"><span class="hljs-attr">apiVersion:</span> <span class="hljs-string">apps/v1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">Deployment</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">node-microservice</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">replicas:</span> <span class="hljs-number">3</span>
  <span class="hljs-attr">selector:</span>
    <span class="hljs-attr">matchLabels:</span>
      <span class="hljs-attr">app:</span> <span class="hljs-string">node-microservice</span>
  <span class="hljs-attr">template:</span>
    <span class="hljs-attr">metadata:</span>
      <span class="hljs-attr">labels:</span>
        <span class="hljs-attr">app:</span> <span class="hljs-string">node-microservice</span>
    <span class="hljs-attr">spec:</span>
      <span class="hljs-attr">containers:</span>
      <span class="hljs-bullet">-</span> <span class="hljs-attr">name:</span> <span class="hljs-string">node-microservice</span>
        <span class="hljs-attr">image:</span> <span class="hljs-string">node-microservice:latest</span>
        <span class="hljs-attr">ports:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">containerPort:</span> <span class="hljs-number">8080</span>
</code></pre>
<p>In this code, you can see how a simple Kubernetes Deployment YAML configuration is used to define the deployment of a Node.js microservice in a Kubernetes cluster. Kubernetes, as a container orchestration tool, automates many critical tasks such as scaling, load balancing, and self-healing.</p>
<p>This configuration ensures that your Node.js microservice is deployed in a controlled and repeatable manner, handling the lifecycle of the application containers effectively.</p>
<p>The first line, <code>apiVersion: apps/v1</code>, specifies the version of the Kubernetes API that this configuration is using. The <code>apps/v1</code> API version is commonly used for managing applications deployed within Kubernetes, such as Deployments, StatefulSets, and DaemonSets. This ensures compatibility with the Kubernetes cluster where the configuration will be applied.</p>
<p>The <code>kind: Deployment</code> field specifies that this configuration defines a <strong>Deployment</strong> resource in Kubernetes. A Deployment ensures that a specified number of identical Pods (which run the containers of your application) are running at all times.</p>
<p>It is used for managing the rollout and scaling of applications while also handling updates in a declarative manner. This is one of the most commonly used resources in Kubernetes to maintain application availability.</p>
<p>The <code>metadata</code> section defines basic information about the deployment, such as the name of the deployment (<code>name: node-microservice</code>). This name identifies the deployment resource within the Kubernetes cluster, making it easier to reference and manage.</p>
<p>In the <code>spec</code> section, the deployment's configuration is defined in detail. The <code>replicas: 3</code> line specifies that Kubernetes should maintain three copies (replicas) of the Node.js microservice running at all times.</p>
<p>This ensures high availability, as Kubernetes will automatically replace any failed Pods with new ones. If one Pod goes down for any reason, another will be started in its place.</p>
<p>The <code>selector</code> field defines how Kubernetes identifies which Pods are managed by this Deployment. The <code>matchLabels</code> section specifies that the Pods with the label <code>app: node-microservice</code> should be included.</p>
<p>This allows Kubernetes to group and manage related Pods based on labels, ensuring that the correct set of Pods is scaled, updated, and rolled back as needed.</p>
<p>The <code>template</code> field defines the structure of the Pods that will be created by this Deployment. Inside the <code>template</code>, <code>metadata</code> defines labels that will be applied to the Pods, ensuring they match the <code>selector</code> defined earlier.</p>
<p>The <code>spec</code> field specifies the container details for the Pod, including the container name (<code>name: node-microservice</code>), the container image (<code>image: node-microservice:latest</code>), and the ports to be exposed (<code>containerPort: 8080</code>). The image refers to a Docker image stored in a registry, and <code>latest</code> indicates the most recent version of that image.</p>
<p>By specifying the container port as 8080, this tells Kubernetes which port the application inside the container will be listening to. This is critical for networking within the cluster, as other services can connect to the Pods using this port.</p>
<p>Overall, this Deployment YAML is a simple yet powerful configuration for managing a Node.js microservice in Kubernetes. Kubernetes will handle the scaling (with three replicas), the application’s high availability, and the management of the Pods that run the application, making it much easier to deploy and manage microservices in a production environment.</p>
<h4 id="heading-helm-charts-and-kubernetes-operators"><strong>Helm Charts and Kubernetes Operators</strong></h4>
<p><a target="_blank" href="https://helm.sh/"><strong>Helm</strong></a> is a package manager for Kubernetes, simplifying deployment. <a target="_blank" href="https://www.cncf.io/blog/2022/06/15/kubernetes-operators-what-are-they-some-examples/"><strong>Kubernetes Operators</strong></a> extend Kubernetes functionalities to manage complex applications.</p>
<p>Helm can deploy an entire microservices stack (for example, a web service, database, and so on) with a single command.</p>
<pre><code class="lang-bash">helm install my-app ./chart
</code></pre>
<p>This code illustrates how you can use Helm to install an application on a Kubernetes cluster. Helm acts as a package manager for Kubernetes, simplifying the process of deploying and managing applications by using <strong>Helm Charts</strong>. Helm Charts are pre-configured application templates that define the resources necessary to deploy an application in Kubernetes.</p>
<p>With a single command like <code>helm install my-app ./chart</code>, you can deploy an entire microservice stack or application on Kubernetes, including web services, databases, and other components, all with the configuration specified in the chart.</p>
<p>The command <code>helm install my-app ./chart</code> is performing several key actions. First, it tells Helm to install a new application named <code>my-app</code>. The <code>./chart</code> path refers to the location of the Helm Chart on your local file system.</p>
<p>This chart contains all the Kubernetes manifest files, configurations, and templates required to deploy the application. When you run this command, Helm takes these resources, processes any templates with user-specific values, and then communicates with the Kubernetes API server to create the necessary Kubernetes resources, such as Pods, Deployments, Services, ConfigMaps, and more.</p>
<p>By using Helm, you abstract away the complexity of managing multiple Kubernetes resources and dependencies. Instead of manually creating and configuring each resource (which can be error-prone and time-consuming), you use the Helm Chart to define everything in one place.</p>
<p>This makes Helm a powerful tool for managing complex applications, particularly microservices, by encapsulating everything needed for deployment and ensuring consistency across different environments.</p>
<p>Kubernetes Operators also extend the functionality of Helm by providing custom resources and controllers that automate the management of complex, stateful applications.</p>
<p>While Helm can handle the deployment, Operators can manage the lifecycle of the application after deployment, including tasks such as backups, scaling, and updates.</p>
<p>This combination of Helm and Kubernetes Operators ensures that your microservices are not only deployed efficiently but also managed intelligently through their entire lifecycle.</p>
<h3 id="heading-cicd-pipelines-and-best-practices"><strong>CI/CD Pipelines and Best Practices</strong></h3>
<p>CI/CD pipelines automate the process of integrating code changes, testing, and deploying them into production.</p>
<p>This enables rapid and frequent delivery of updates while maintaining high-quality code.</p>
<p><strong>Best Practices</strong>:</p>
<ul>
<li><p>Use <strong>small, frequent commits</strong> to enable easier testing and rollback.</p>
</li>
<li><p>Ensure each service can be tested and deployed independently.</p>
</li>
</ul>
<h4 id="heading-tools-and-platforms-for-cicd">Tools and Platforms for CI/CD</h4>
<ol>
<li><p><a target="_blank" href="https://www.jenkins.io/"><strong>Jenkins</strong></a>: Open-source automation tool for building CI/CD pipelines.</p>
</li>
<li><p><a target="_blank" href="https://docs.gitlab.com/ee/ci/"><strong>GitLab CI/CD</strong></a>: Integrated with GitLab, it provides built-in CI/CD tools.</p>
</li>
<li><p><a target="_blank" href="https://circleci.com/"><strong>CircleCI</strong></a>: Offers fast and efficient pipelines for continuous delivery.</p>
</li>
</ol>
<p><strong>Jenkins Pipeline for Microservice Deployment</strong>:</p>
<pre><code class="lang-java">pipeline {
    agent any
    stages {
        stage(<span class="hljs-string">'Build'</span>) {
            steps {
                sh <span class="hljs-string">'npm install'</span>
            }
        }
        stage(<span class="hljs-string">'Test'</span>) {
            steps {
                sh <span class="hljs-string">'npm test'</span>
            }
        }
        stage(<span class="hljs-string">'Deploy'</span>) {
            steps {
                sh <span class="hljs-string">'docker build -t my-app .'</span>
                sh <span class="hljs-string">'docker push my-app:latest'</span>
            }
        }
    }
}
</code></pre>
<p>In this snippet, you can see how a Jenkins Pipeline is defined to automate the process of building, testing, and deploying a Node.js microservice using Docker. This scripted pipeline structure is specified in a Jenkinsfile and leverages three stages: Build, Test, and Deploy.</p>
<p>Each stage in the pipeline represents a distinct step in the continuous integration (CI) and continuous deployment (CD) lifecycle for a microservice.</p>
<p>In the <strong>Build</strong> stage, the pipeline runs the command <code>npm install</code> to install all the dependencies specified in the <code>package.json</code> file. This step is essential for setting up the application's environment and ensuring that all required libraries are in place for subsequent stages.</p>
<p>The command <code>sh</code> is a Jenkins Pipeline step that allows the use of shell commands, such as those for Node.js package management.</p>
<p>In the <strong>Test</strong> stage, the pipeline executes <code>npm test</code> to run the test suite defined in the project. Testing at this stage ensures that the microservice’s code functions correctly before it’s packaged for deployment.</p>
<p>This stage is critical for catching issues early in the CI/CD process, allowing developers to detect and address bugs before they reach the deployment environment.</p>
<p>The <strong>Deploy</strong> stage begins with the command <code>docker build -t my-app .</code>, which creates a Docker image-tagged <code>my-app</code> from the application source code and configuration files in the current directory (<code>.</code>).</p>
<p>After building the Docker image, the command <code>docker push my-app:latest</code> uploads the image to a container registry (assuming <code>my-app</code> is configured with a registry URL in the Docker environment). This step makes the built container image available for deployment to any environment that pulls images from this registry.</p>
<p>By organizing these steps in a Jenkins pipeline, you create a streamlined, automated workflow that allows you to easily reproduce the process of building, testing, and deploying the application across multiple environments.</p>
<p>This setup reduces the risk of human error, accelerates deployment, and ensures consistent results with every commit or code change.</p>
<h4 id="heading-automated-testing-and-deployment-strategies"><strong>Automated Testing and Deployment Strategies</strong></h4>
<ul>
<li><p><strong>Blue/Green Deployment</strong>: Involves running two versions of the service simultaneously.<br>  Traffic is gradually shifted to the new version, ensuring zero downtime.</p>
</li>
<li><p><strong>Canary Releases</strong>: Gradually introduce a new version of a service to a subset of users, allowing for monitoring and rollback in case of issues.</p>
</li>
</ul>
<h2 id="heading-monitoring-and-logging"><strong>Monitoring and Logging</strong></h2>
<p>Effective monitoring and logging are fundamental to maintaining the health and performance of a microservices-based application. As microservices often operate in distributed environments, it becomes challenging to track, diagnose, and troubleshoot issues. Without proper visibility into the system’s behavior, you risk operational inefficiencies, performance bottlenecks, and increased downtime.</p>
<p>In this section, we will focus on how to implement robust monitoring and logging practices that ensure you can effectively track and manage the behavior of microservices in real-time.</p>
<p>We'll explore the tools and frameworks available for monitoring system health, gathering performance metrics, and collecting logs from different microservices in your application.</p>
<p>We'll also discuss how these practices can support proactive issue resolution by allowing for timely alerts and more insightful data for debugging.</p>
<p>Then we’ll dive into the importance of centralized logging systems like ELK Stack (Elasticsearch, Logstash, and Kibana), and how monitoring solutions such as Prometheus and Grafana provide metrics and visualizations to observe your services' health.</p>
<p>Finally, we’ll cover tracing techniques that can help pinpoint the flow of requests across microservices, ensuring quick resolution of performance or failure issues.</p>
<p>By the end of this section, you'll understand how to implement a comprehensive monitoring and logging strategy that ensures your microservices architecture operates smoothly and reliably.</p>
<h3 id="heading-centralized-logging-solutions-elk-stack-fluentd"><strong>Centralized Logging Solutions (ELK Stack, Fluentd)</strong></h3>
<p>Microservices generate logs across many instances. Centralized logging solutions collect and store logs in a single location, simplifying analysis.</p>
<ul>
<li><strong>ELK Stack (Elasticsearch, Logstash, Kibana)</strong>: Common for centralized logging, enabling full-text search and visualizations.</li>
</ul>
<h3 id="heading-monitoring-and-observability-tools-prometheus-grafana-datadog"><strong>Monitoring and Observability Tools (Prometheus, Grafana, Datadog)</strong></h3>
<p>Monitoring tools track the performance and health of microservices. <a target="_blank" href="https://prometheus.io/"><strong>Prometheus</strong></a> collects metrics, and <a target="_blank" href="https://grafana.com/"><strong>Grafana</strong></a> visualizes them in dashboards.</p>
<p><strong>Prometheus (Monitoring Node.js Microservice)</strong>:</p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> client = <span class="hljs-built_in">require</span>(<span class="hljs-string">'prom-client'</span>);

<span class="hljs-comment">// Create a counter metric</span>
<span class="hljs-keyword">const</span> requestCounter = <span class="hljs-keyword">new</span> client.Counter({
    <span class="hljs-attr">name</span>: <span class="hljs-string">'node_requests_total'</span>,
    <span class="hljs-attr">help</span>: <span class="hljs-string">'Total number of requests'</span>
});

<span class="hljs-comment">// Increment counter on each request</span>
app.use(<span class="hljs-function">(<span class="hljs-params">req, res, next</span>) =&gt;</span> {
    requestCounter.inc();
    next();
});
</code></pre>
<p>The following code shows the process of how Prometheus metrics are integrated into a Node.js application using the <code>prom-client</code> library to monitor API requests.</p>
<p>Prometheus is a popular tool for monitoring and alerting in microservices environments, often used to track and visualize system health metrics like request counts, response times, and error rates.</p>
<p>Here, the code is focused on implementing a simple counter metric to monitor the total number of requests the application receives.</p>
<p>First, the <code>prom-client</code> module is imported to set up Prometheus-compatible metrics in the application. The <code>Counter</code> class from <code>prom-client</code> is used to define a new counter metric, named <code>node_requests_total</code>, with a description (via the <code>help</code> property) of "Total number of requests."</p>
<p>Counters in Prometheus are designed for tracking cumulative values, like the count of requests or the number of errors, and are ideal for metrics that always increase, such as a request count.</p>
<p>The middleware function then increments this counter on every incoming request by calling <a target="_blank" href="http://requestCounter.inc"><code>requestCounter.inc</code></a><code>()</code>. This middleware is added to the Express <code>app</code> instance using <code>app.use()</code>, which means it will execute for every incoming request, incrementing the <code>requestCounter</code> metric.</p>
<p>Each time a new request is processed, Prometheus records this increment, allowing the total count of requests to be monitored over time.</p>
<p>This setup allows Prometheus to pull these metrics at regular intervals from the application’s <code>/metrics</code> endpoint (if configured).</p>
<p>By tracking the <code>node_requests_total</code> counter, you can gain insights into traffic patterns and detect sudden increases or decreases in request volume, which can be crucial for monitoring system performance and ensuring service reliability.</p>
<p>This basic example demonstrates how to set up and use Prometheus metrics to gain visibility into microservice activity</p>
<h3 id="heading-distributed-tracing-jaeger-zipkin"><strong>Distributed Tracing (Jaeger, Zipkin)</strong></h3>
<p>In microservices, tracking a request's journey across services is crucial. Distributed tracing tools like <a target="_blank" href="https://www.jaegertracing.io/"><strong>Jaeger</strong></a> and <a target="_blank" href="https://zipkin.io/"><strong>Zipkin</strong></a> provide visibility into how requests propagate across services.</p>
<p>Distributed tracing is like tracking a package’s journey through multiple shipping hubs, providing insights into where delays occur.</p>
<h3 id="heading-security-considerations"><strong>Security Considerations</strong></h3>
<h4 id="heading-securing-apis-and-inter-service-communication-oauth-jwt"><strong>Securing APIs and Inter-Service Communication (OAuth, JWT)</strong></h4>
<ol>
<li><p><strong>OAuth 2.0</strong>: A framework that allows users to grant third-party applications access to their resources without sharing credentials.</p>
</li>
<li><p><strong>JWT (JSON Web Tokens)</strong>: Used for secure, stateless authentication between services.</p>
</li>
</ol>
<p><strong>Securing API with JWT in Node.js:</strong></p>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> jwt = <span class="hljs-built_in">require</span>(<span class="hljs-string">'jsonwebtoken'</span>);

<span class="hljs-comment">// Middleware to verify JWT</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">verifyToken</span>(<span class="hljs-params">req, res, next</span>) </span>{
    <span class="hljs-keyword">const</span> token = req.headers[<span class="hljs-string">'authorization'</span>];
    <span class="hljs-keyword">if</span> (!token) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">403</span>).send(<span class="hljs-string">'No token provided.'</span>);

    jwt.verify(token, <span class="hljs-string">'secretkey'</span>, <span class="hljs-function">(<span class="hljs-params">err, decoded</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (err) <span class="hljs-keyword">return</span> res.status(<span class="hljs-number">500</span>).send(<span class="hljs-string">'Failed to authenticate token.'</span>);
        req.userId = decoded.id;
        next();
    });
}

app.use(verifyToken);
</code></pre>
<p>In this implementation, you’ll notice how JWT (JSON Web Token) authentication is implemented in a Node.js application using the <code>jsonwebtoken</code> library to secure API access. JWT is commonly used to verify the identity of a user and ensure that only authenticated users can access certain endpoints or perform sensitive actions.</p>
<p>Here, a middleware function <code>verifyToken</code> is defined to check the presence and validity of a JWT token on each request. In Node.js applications, middleware is a function that has access to the request (<code>req</code>) and response (<code>res</code>) objects and can perform operations before passing control to the next middleware or route handler.</p>
<p>By setting up this middleware, you enforce token verification on every request, ensuring that all subsequent routes are protected.</p>
<p>The <code>verifyToken</code> function first checks for a token in the request headers under the <code>authorization</code> field. If no token is provided, it immediately returns a <code>403</code> status with a message indicating "No token provided," blocking access to unauthorized users.</p>
<p>If a token is present, the function uses <code>jwt.verify()</code> to decode and validate the token against a secret key, here referred to as <code>'secretkey'</code>. If the token verification fails (for example, if the token is expired or has been tampered with), an error is returned with a <code>500</code> status code and a message indicating "Failed to authenticate token."</p>
<p>If the token is valid, the decoded token’s <code>id</code> (which could represent the user's ID or other identifying information) is assigned to <code>req.userId</code>, making it available for any downstream functions to use, and the <code>next()</code> function is called to proceed to the next middleware or route handler.</p>
<p>Finally, <code>app.use(verifyToken);</code> applies this middleware globally to all routes, meaning every incoming request to the API will go through this authentication check. This setup is useful in securing sensitive routes, as it prevents unauthorized users from accessing data or functionalities they shouldn’t have access to.</p>
<p>With this structure, you can also customize the JWT verification process or apply this middleware selectively to specific routes depending on the security requirements of your application.</p>
<h4 id="heading-network-security-and-firewall-configurations"><strong>Network Security and Firewall Configurations</strong></h4>
<p>Securing the network layer involves setting up firewall rules, VPNs, and Virtual Private Clouds (VPCs) to control access between services.</p>
<ul>
<li><strong>Example</strong>: Configure <strong>AWS Security Groups</strong> to restrict access to a microservice only from specific IP addresses or other services.</li>
</ul>
<h4 id="heading-compliance-and-data-protection-gdpr-hipaa"><strong>Compliance and Data Protection (GDPR, HIPAA)</strong></h4>
<p>Microservices handling sensitive data must comply with data protection regulations like <a target="_blank" href="https://gdpr-info.eu/"><strong>GDPR (General Data Protection Regulation)</strong></a> and <a target="_blank" href="https://www.hhs.gov/hipaa/index.html"><strong>HIPAA (Health Insurance Portability and Accountability Act)</strong></a>. This involves:</p>
<ul>
<li><p>Data encryption (in transit and at rest).</p>
</li>
<li><p>Role-based access control (RBAC).</p>
</li>
<li><p>Regular auditing and reporting.</p>
</li>
</ul>
<p>Managing microservices in the cloud requires leveraging cloud-native tools, container orchestration, CI/CD practices, monitoring, and security measures.</p>
<p>By implementing these strategies, microservices can be deployed and managed effectively in the cloud environment while ensuring reliability, scalability, and security.</p>
<h2 id="heading-case-studies-and-real-world-examples">Case Studies and Real-World Examples</h2>
<p>The section explores how microservices architecture has been implemented across various industries, offering insights into the successes, challenges, and innovations from leading companies.</p>
<p>By examining real-world applications, you’ll see how microservices are used to solve complex scalability and flexibility issues and how different companies have approached architecture, deployment, and management.</p>
<p>This section includes detailed case studies from technology giants and enterprises in sectors such as e-commerce, finance, and media, showcasing how each adapted microservices to meet unique demands.</p>
<p>By analyzing both the strategies that drove successful implementations and the lessons learned from obstacles encountered, this part provides a practical perspective on microservices adoption and illustrates how abstract concepts are applied in real-world environments.</p>
<p>Through these examples, you should be able to grasp how microservices might benefit your own applications, gaining actionable insights for building, scaling, and optimizing microservices in diverse operational contexts.</p>
<h3 id="heading-case-study-1-e-commerce-platform"><strong>Case Study 1: E-Commerce Platform</strong></h3>
<p>First, we’ll look at the case of an e-commerce platform with multiple microservices handling product listings, user management, order processing, and payment transactions.</p>
<p>Think of the platform as a large department store with separate sections for clothing, electronics, and groceries. Each section (microservice) manages its own inventory and operations.</p>
<h4 id="heading-architecture"><strong>Architecture</strong></h4>
<h6 id="heading-microservices-involved"><strong>Microservices involved:</strong></h6>
<ul>
<li><p><strong>Product Service:</strong> Manages product catalog and search functionality.</p>
</li>
<li><p><strong>User Service:</strong> Handles user registration, authentication, and profile management.</p>
</li>
<li><p><strong>Order Service:</strong> Processes orders and manages order history.</p>
</li>
<li><p><strong>Payment Service:</strong> Handles payment processing and transactions.</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// Service Definitions</span>

<span class="hljs-comment">// Product Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.products = [];
  }

  addProduct(product) {
    <span class="hljs-built_in">this</span>.products.push(product);
    <span class="hljs-keyword">return</span> product;
  }

  searchProducts(query) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.products.filter(<span class="hljs-function"><span class="hljs-params">p</span> =&gt;</span> p.name.includes(query));
  }
}

<span class="hljs-comment">// User Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.users = [];
  }

  registerUser(user) {
    <span class="hljs-built_in">this</span>.users.push(user);
    <span class="hljs-keyword">return</span> user;
  }

  authenticateUser(username, password) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.users.find(<span class="hljs-function"><span class="hljs-params">u</span> =&gt;</span> u.username === username &amp;&amp; u.password === password);
  }
}

<span class="hljs-comment">// Order Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.orders = [];
  }

  createOrder(order) {
    <span class="hljs-built_in">this</span>.orders.push(order);
    <span class="hljs-keyword">return</span> order;
  }

  getOrder(orderId) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.orders.find(<span class="hljs-function"><span class="hljs-params">o</span> =&gt;</span> o.id === orderId);
  }
}

<span class="hljs-comment">// Payment Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentService</span> </span>{
  processPayment(paymentInfo) {
    <span class="hljs-comment">// Simulate payment processing</span>
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Payment of <span class="hljs-subst">${paymentInfo.amount}</span> processed successfully`</span>;
  }
}
</code></pre>
<p>The code above illustrates how each of the four services in a microservices-oriented application is defined independently, with dedicated methods for handling distinct functionalities related to products, users, orders, and payments.</p>
<p>This approach exemplifies how each service in a microservice architecture is specialized and modular, with minimal dependencies on other services, which makes the codebase easier to manage, test, and scale.</p>
<p>The <code>ProductService</code> class manages a list of products, providing methods like <code>addProduct</code> to add a product to the list and <code>searchProducts</code> to filter products based on a search query. The <code>addProduct</code> method appends a new product to an array, simulating a lightweight in-memory data store.</p>
<p>The <code>searchProducts</code> method then allows users to search for products by name, providing a simple but effective mechanism for retrieving relevant products based on the user’s input.</p>
<p>The <code>UserService</code> class represents the logic for handling user-related operations. It includes a <code>registerUser</code> method to add new users to the system, and an <code>authenticateUser</code> method to validate credentials.</p>
<p>When a user attempts to log in, <code>authenticateUser</code> checks for a user entry that matches both the provided username and password, simulating a basic form of user authentication.</p>
<p>This demonstrates how user authentication can be encapsulated within a single service, ensuring the functionality is cohesive and logically separated from other service responsibilities.</p>
<p>The <code>OrderService</code> class is focused on managing orders. The <code>createOrder</code> method allows for creating a new order, appending it to the <code>orders</code> array, and returning the created order as confirmation.</p>
<p>The <code>getOrder</code> method retrieves a specific order based on its ID, offering a way to access individual order details. This separation of concerns keeps the order-handling logic contained within its own service, making it easy to scale independently as order volumes increase.</p>
<p>Finally, the <code>PaymentService</code> class provides a <code>processPayment</code> method to simulate payment processing. This method takes payment information, such as an amount, and returns a confirmation message to indicate successful processing.</p>
<p>Although the <code>processPayment</code> method here is simple, in a real-world scenario, it would interact with external payment processing systems. By isolating payment logic in its own service, it becomes straightforward to modify or replace the payment processing mechanism without affecting other parts of the application.</p>
<p>This setup demonstrates how each service can independently perform its designated tasks, enabling scalable and maintainable code. Each service manages its own state and operations without interfering with others, allowing for independent development, testing, and deployment of each service, which is a key benefit of microservice architecture.</p>
<h4 id="heading-challenges-and-solutions"><strong>Challenges and Solutions</strong></h4>
<ul>
<li><p><strong>Challenge:</strong> Ensuring consistent data across services, such as synchronizing user data with orders.</p>
</li>
<li><p><strong>Solution:</strong> Implementing a shared data store or using event-driven architecture to keep data in sync.</p>
</li>
</ul>
<p>It’s like having a central inventory system that updates stock levels across all departments in real time.</p>
<h4 id="heading-lessons-learned"><strong>Lessons Learned:</strong></h4>
<ul>
<li><p><strong>Scalability:</strong> Separating services allowed the platform to scale individual components (for example, product search) based on demand.</p>
</li>
<li><p><strong>Resilience:</strong> Microservices architecture improved fault tolerance. If one service failed, the rest continued to operate.</p>
</li>
</ul>
<h3 id="heading-case-study-2-streaming-media-service"><strong>Case Study 2: Streaming Media Service</strong></h3>
<p>The next case we’ll look at is a streaming service providing video content with features like recommendation engines, user profiles, and content delivery.</p>
<p>It’s similar to a cable TV provider with different channels (services) for live TV, on-demand content, and user recommendations.</p>
<h4 id="heading-architecture-1"><strong>Architecture</strong></h4>
<h6 id="heading-microservices-involved-1"><strong>Microservices involved:</strong></h6>
<ul>
<li><p><strong>Content Service:</strong> Manages video content and metadata.</p>
</li>
<li><p><strong>Recommendation Service:</strong> Provides personalized content recommendations based on user behavior.</p>
</li>
<li><p><strong>User Profile Service:</strong> Handles user profiles, preferences, and watch history.</p>
</li>
<li><p><strong>Streaming Service:</strong> Manages video streaming and delivery.</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// Service Definitions</span>

<span class="hljs-comment">// Content Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ContentService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.contents = [];
  }

  addContent(content) {
    <span class="hljs-built_in">this</span>.contents.push(content);
    <span class="hljs-keyword">return</span> content;
  }

  getContent(id) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.contents.find(<span class="hljs-function"><span class="hljs-params">c</span> =&gt;</span> c.id === id);
  }
}

<span class="hljs-comment">// Recommendation Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RecommendationService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.recommendations = {};
  }

  generateRecommendations(userId) {
    <span class="hljs-comment">// Simulate recommendation logic</span>
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.recommendations[userId] || [];
  }
}

<span class="hljs-comment">// User Profile Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserProfileService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.profiles = [];
  }

  getUserProfile(userId) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.profiles.find(<span class="hljs-function"><span class="hljs-params">p</span> =&gt;</span> p.userId === userId);
  }
}

<span class="hljs-comment">// Streaming Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StreamingService</span> </span>{
  streamContent(contentId) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Streaming content with ID: <span class="hljs-subst">${contentId}</span>`</span>;
  }
}
</code></pre>
<p>In the code above, you can see how each service encapsulates specific functionalities related to content management, user recommendations, user profiles, and streaming, typical in a media platform with a microservices architecture.</p>
<p>Each service class represents a distinct part of the application, ensuring modularity and separation of concerns, which aligns with the microservice philosophy.</p>
<p>The <code>ContentService</code> class is designed to manage content data. It contains an array, <code>this.contents</code>, which acts as a temporary in-memory storage for content objects. The <code>addContent</code> method allows new content to be added to this array and returns the added content, allowing confirmation of a successful addition.</p>
<p>The <code>getContent</code> method retrieves a specific content item by ID, simulating a database search. In this code, you can see how <code>addContent</code> and <code>getContent</code> work to handle basic content management within a defined scope, enabling simple CRUD (Create, Read, Update, Delete) operations that could later expand with a persistent data store.</p>
<p>The <code>RecommendationService</code> class focuses on providing content recommendations based on user IDs. Here, <code>this.recommendations</code> is an object where recommendations for each user can be stored and accessed.</p>
<p>The <code>generateRecommendations</code> method fetches recommendations for a given <code>userId</code>, providing a placeholder for more sophisticated recommendation logic, such as algorithms that analyze user preferences or historical data.</p>
<p>Also, you can see how <code>generateRecommendations</code> works to encapsulate user-specific recommendations, allowing for customization and personalization of content, which is crucial for engagement in media services.</p>
<p>The <code>UserProfileService</code> class manages user profile data. The <code>getUserProfile</code> method retrieves a specific user profile based on <code>userId</code>, making it possible to access user-specific information like preferences or watch history.</p>
<p>This service has its own in-memory array, <code>this.profiles</code>, which represents user profile storage. In this code, you can see how <code>getUserProfile</code> works independently to fetch relevant profile information without relying on other services, allowing it to operate autonomously and at scale.</p>
<p>Lastly, the <code>StreamingService</code> class is responsible for handling content streaming. It includes the <code>streamContent</code> method, which takes a <code>contentId</code> and simulates streaming functionality by returning a message confirming the stream of the specified content.</p>
<p>This class doesn’t maintain state but performs an action based on a request, making it lightweight and efficient for handling multiple streaming requests. You can also see how <code>streamContent</code> works by focusing solely on providing a streaming response, aligning with the principle of single responsibility and ensuring that streaming functionality remains isolated from other application logic.</p>
<p>These services illustrate how dividing an application into focused, specialized services allows each to operate independently. Each service’s methods are designed to be extensible, meaning they can grow in functionality without interfering with other parts of the application.</p>
<p>This architecture is highly advantageous for complex applications, as it allows for individual services to be scaled, modified, and maintained without impacting the overall system.</p>
<h4 id="heading-challenges-and-solutions-1"><strong>Challenges and Solutions:</strong></h4>
<ul>
<li><p><strong>Challenge:</strong> Handling high traffic and ensuring smooth streaming during peak times.</p>
</li>
<li><p><strong>Solution:</strong> Implementing content delivery networks (CDNs) and optimizing streaming protocols.</p>
</li>
</ul>
<p>It’s like distributing TV signals through multiple antennas to ensure clear reception even in high-demand areas.</p>
<h4 id="heading-lessons-learned-1"><strong>Lessons Learned:</strong></h4>
<ul>
<li><p><strong>Performance:</strong> CDN integration improved content delivery speed and reduced latency.</p>
</li>
<li><p><strong>Personalization:</strong> Personalized recommendations increased user engagement and satisfaction.</p>
</li>
</ul>
<h3 id="heading-case-study-3-financial-services-application"><strong>Case Study 3: Financial Services Application</strong></h3>
<p>For our third case study, we’ll consider a financial services application with microservices for account management, transaction processing, and fraud detection.</p>
<p>it’s similar to a bank with different departments for account services, transaction handling, and security checks.</p>
<h4 id="heading-architecture-2"><strong>Architecture</strong></h4>
<h6 id="heading-microservices-involved-2"><strong>Microservices involved:</strong></h6>
<ul>
<li><p><strong>Account Service:</strong> Manages user accounts and balances.</p>
</li>
<li><p><strong>Transaction Service:</strong> Handles transactions and transfers.</p>
</li>
<li><p><strong>Fraud Detection Service:</strong> Monitors and detects suspicious activities.</p>
</li>
</ul>
<pre><code class="lang-javascript"><span class="hljs-comment">// Service Definitions</span>

<span class="hljs-comment">// Account Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AccountService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.accounts = [];
  }

  createAccount(account) {
    <span class="hljs-built_in">this</span>.accounts.push(account);
    <span class="hljs-keyword">return</span> account;
  }

  getAccount(accountId) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.accounts.find(<span class="hljs-function"><span class="hljs-params">a</span> =&gt;</span> a.id === accountId);
  }
}

<span class="hljs-comment">// Transaction Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TransactionService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.transactions = [];
  }

  processTransaction(transaction) {
    <span class="hljs-built_in">this</span>.transactions.push(transaction);
    <span class="hljs-keyword">return</span> transaction;
  }
}

<span class="hljs-comment">// Fraud Detection Service</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FraudDetectionService</span> </span>{
  detectFraud(transaction) {
    <span class="hljs-comment">// Simulate fraud detection</span>
    <span class="hljs-keyword">if</span> (transaction.amount &gt; <span class="hljs-number">10000</span>) {
      <span class="hljs-keyword">return</span> <span class="hljs-string">'Suspicious transaction detected'</span>;
    }
    <span class="hljs-keyword">return</span> <span class="hljs-string">'Transaction is safe'</span>;
  }
}
</code></pre>
<p>Here, the code illustrates how each class represents a specific service within a financial application, reflecting the modular approach of a microservices architecture.</p>
<p>Each service focuses on a single aspect of the financial domain—account management, transaction handling, and fraud detection—ensuring the code remains organized, reusable, and scalable as each class can operate independently.</p>
<p>The <code>AccountService</code> class is responsible for managing user accounts. Within the constructor, <code>this.accounts</code> is initialized as an empty array to serve as temporary in-memory storage for account objects.</p>
<p>The <code>createAccount</code> method allows new accounts to be created and added to the <code>accounts</code> array, returning the created account for verification or further use. The <code>getAccount</code> method searches through <code>this.accounts</code> to find an account that matches a specific <code>accountId</code>. In this code, you can see how <code>createAccount</code> and <code>getAccount</code> work together to provide basic CRUD operations for managing account data.</p>
<p>The <code>TransactionService</code> class focuses on processing and recording transactions. The <code>this.transactions</code> array is set up within the constructor to store individual transaction records. The <code>processTransaction</code> method receives a transaction object, adds it to the transactions array, and returns it, simulating a simple method to store and track transactions.</p>
<p>Further in the code, you can see how <code>processTransaction</code> works as a core feature of this service, facilitating transaction management independently from other services like fraud detection or account management.</p>
<p>The <code>FraudDetectionService</code> class is built to monitor transactions for potential fraud. It includes a single method, <code>detectFraud</code>, that evaluates a given transaction object based on a simple rule: if the transaction amount exceeds $10,000, it is considered “suspicious.” If the amount is less than or equal to $10,000, it is classified as “safe.”</p>
<p>While this is a basic example, it demonstrates how logic specific to fraud detection can be encapsulated within its own service, allowing for future expansion or integration with advanced fraud detection algorithms. You can also see how <code>detectFraud</code> works to isolate and centralize fraud detection logic, making it easy to refine this logic independently as requirements evolve.</p>
<p>Overall, this setup illustrates how microservices can enhance modularity by separating concerns and isolating different areas of functionality. Each class has its specific responsibilities, ensuring that each service can be developed, scaled, or maintained independently without affecting the others.</p>
<p>This approach aligns well with a microservices architecture, as it supports scalability, code reusability, and ease of testing, allowing each service to evolve alongside the needs of the application.</p>
<h4 id="heading-challenges-and-solutions-2"><strong>Challenges and Solutions:</strong></h4>
<ul>
<li><p><strong>Challenge:</strong> Ensuring security and compliance with financial regulations.</p>
</li>
<li><p><strong>Solution:</strong> Implementing robust encryption, secure authentication mechanisms, and regular audits.</p>
</li>
</ul>
<p>It’s like having a secure vault and stringent checks to protect and verify financial transactions.</p>
<h4 id="heading-lessons-learned-2"><strong>Lessons Learned:</strong></h4>
<ul>
<li><p><strong>Security:</strong> Advanced fraud detection algorithms improved the system's ability to identify and prevent fraudulent transactions.</p>
</li>
<li><p><strong>Compliance:</strong> Regular updates and compliance checks ensured adherence to financial regulations.</p>
</li>
</ul>
<h2 id="heading-real-world-examples-of-microservices"><strong>Real-World Examples of Microservices</strong></h2>
<p>Microservices are widely adopted by some of the largest tech companies to scale their platforms, provide high availability, and manage complex functionalities.</p>
<p>Let's look at how companies like Netflix, Amazon, and Uber implement microservices. We'll look at some conceptual examples in JavaScript to help illustrate how these architectures work.</p>
<h3 id="heading-1-netflix-scaling-content-and-recommendations"><strong>1. Netflix: Scaling Content and Recommendations</strong></h3>
<p>Netflix, one of the pioneers of microservices architecture, uses microservices to handle multiple facets of its service, such as managing its vast content library, personalized recommendations, and streaming capabilities.</p>
<p>Each microservice is responsible for a specific part of the platform, making it easier to scale and update independently.</p>
<h4 id="heading-key-microservices-at-netflix"><strong>Key Microservices at Netflix</strong></h4>
<ul>
<li><p><strong>Content Service</strong>: Manages the catalog of shows and movies.</p>
</li>
<li><p><strong>Recommendation Service</strong>: Handles personalized recommendations based on user behavior.</p>
</li>
<li><p><strong>Streaming Service</strong>: Ensures content is delivered seamlessly to users across the globe.</p>
</li>
</ul>
<p><strong>Conceptual Example: Netflix Microservice</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Content service microservice responsible for handling the content catalog</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ContentService</span> </span>{
  getContent(contentId) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Fetching content with ID: <span class="hljs-subst">${contentId}</span>`</span>;
  }
}

<span class="hljs-comment">// Recommendation service microservice responsible for generating recommendations</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RecommendationService</span> </span>{
  generateRecommendations(userId) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Generating recommendations for user: <span class="hljs-subst">${userId}</span>`</span>;
  }
}

<span class="hljs-comment">// Streaming service microservice responsible for streaming content</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StreamingService</span> </span>{
  streamContent(contentId) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Streaming content with ID: <span class="hljs-subst">${contentId}</span>`</span>;
  }
}

<span class="hljs-comment">// NetflixService acting as an orchestrator</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NetflixService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.contentService = <span class="hljs-keyword">new</span> ContentService();
    <span class="hljs-built_in">this</span>.recommendationService = <span class="hljs-keyword">new</span> RecommendationService();
    <span class="hljs-built_in">this</span>.streamingService = <span class="hljs-keyword">new</span> StreamingService();
  }

  recommend(userId) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.recommendationService.generateRecommendations(userId);
  }

  stream(contentId) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.streamingService.streamContent(contentId);
  }
}

<span class="hljs-comment">// Example usage</span>
<span class="hljs-keyword">const</span> netflix = <span class="hljs-keyword">new</span> NetflixService();
<span class="hljs-built_in">console</span>.log(netflix.recommend(<span class="hljs-number">101</span>)); <span class="hljs-comment">// "Generating recommendations for user: 101"</span>
<span class="hljs-built_in">console</span>.log(netflix.stream(<span class="hljs-number">200</span>)); <span class="hljs-comment">// "Streaming content with ID: 200"</span>
</code></pre>
<p>This code demonstrates how several microservices interact together within an orchestrated service architecture, each focusing on a distinct feature relevant to a content-streaming platform.</p>
<p>This code illustrates a modular, microservice-oriented design where individual services manage specific tasks—content retrieval, recommendation generation, and content streaming—while a central orchestrator, <code>NetflixService</code>, coordinates them to provide a cohesive service interface.</p>
<p>The <code>ContentService</code> class represents a microservice dedicated to managing the content catalog. It includes the <code>getContent</code> method, which takes a <code>contentId</code> as input and returns a message indicating that the content with that ID is being fetched.</p>
<p>This setup allows the <code>ContentService</code> to handle any actions related to retrieving or interacting with content independently, encapsulating content management functionality within its own service.</p>
<p>The <code>RecommendationService</code> class focuses on generating recommendations for users. It contains the <code>generateRecommendations</code> method, which receives a <code>userId</code> and returns a message showing that recommendations are being created for the specified user.</p>
<p>In this code, you can see how <code>generateRecommendations</code> works to simulate a recommendation service that could later integrate with recommendation algorithms to provide personalized suggestions based on the user’s profile, history, or preferences.</p>
<p>The <code>StreamingService</code> class is dedicated to streaming content to the user. Its <code>streamContent</code> method takes a <code>contentId</code> and returns a message that the specified content is being streamed.</p>
<p>This method showcases how streaming functionalities are encapsulated separately, allowing for the potential integration of streaming protocols or optimizations that enhance the user experience.</p>
<p>The <code>NetflixService</code> class acts as an orchestrator that ties together the individual services into a unified interface. In the constructor, instances of <code>ContentService</code>, <code>RecommendationService</code>, and <code>StreamingService</code> are created, enabling <code>NetflixService</code> to coordinate these services and manage user requests.</p>
<p>The <code>recommend</code> method uses <code>recommendationService</code> to generate recommendations for a specified user, while the <code>stream</code> method calls <code>streamContent</code> on the <code>streamingService</code> to initiate content streaming.</p>
<p>This code demonstrates how NetflixService functions as a single point of entry that abstracts the internal microservices from the client, allowing clients to interact with a cohesive, streamlined interface without needing to know the details of each underlying service.</p>
<p>This design demonstrates the principles of service orchestration in a microservices architecture. Each individual service can evolve or be replaced independently, without disrupting the entire application, while <code>NetflixService</code> provides a high-level API that clients can use for a smooth user experience.</p>
<p>This type of architecture makes the application more scalable and easier to maintain, as each service focuses on a specific domain while the orchestrator manages their interactions.</p>
<p>In Netflix's real-world architecture, each of these services is built as an independent microservice, allowing them to deploy, scale, and evolve each service independently based on demand.</p>
<h3 id="heading-2-amazon-managing-orders-and-products-at-scale"><strong>2. Amazon: Managing Orders and Products at Scale</strong></h3>
<p>Amazon's vast e-commerce platform depends heavily on microservices for handling everything from product searches to order management, customer service, and payment processing.</p>
<p>By breaking these responsibilities into independent services, Amazon can handle millions of orders daily and ensure a smooth customer experience.</p>
<h4 id="heading-key-microservices-at-amazon"><strong>Key Microservices at Amazon</strong></h4>
<ul>
<li><p><strong>Product Service</strong>: Manages the product catalog, including search and filtering.</p>
</li>
<li><p><strong>Order Service</strong>: Processes and manages orders, tracking, and order history.</p>
</li>
<li><p><strong>Customer Service</strong>: Handles customer-related inquiries and support.</p>
</li>
</ul>
<p><strong>Conceptual Example: Amazon Microservice</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Product service microservice responsible for product search</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductService</span> </span>{
  searchProducts(query) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Searching for products related to: <span class="hljs-subst">${query}</span>`</span>;
  }
}

<span class="hljs-comment">// Order service microservice responsible for creating and managing orders</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderService</span> </span>{
  createOrder(order) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Placing order for items: <span class="hljs-subst">${<span class="hljs-built_in">JSON</span>.stringify(order)}</span>`</span>;
  }
}

<span class="hljs-comment">// AmazonService acting as an orchestrator</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AmazonService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.productService = <span class="hljs-keyword">new</span> ProductService();
    <span class="hljs-built_in">this</span>.orderService = <span class="hljs-keyword">new</span> OrderService();
  }

  searchProducts(query) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.productService.searchProducts(query);
  }

  placeOrder(order) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.orderService.createOrder(order);
  }
}

<span class="hljs-comment">// Example usage</span>
<span class="hljs-keyword">const</span> amazon = <span class="hljs-keyword">new</span> AmazonService();
<span class="hljs-built_in">console</span>.log(amazon.searchProducts(<span class="hljs-string">'laptop'</span>)); <span class="hljs-comment">// "Searching for products related to: laptop"</span>
<span class="hljs-built_in">console</span>.log(amazon.placeOrder([{ <span class="hljs-attr">product</span>: <span class="hljs-string">'laptop'</span>, <span class="hljs-attr">qty</span>: <span class="hljs-number">1</span> }])); <span class="hljs-comment">// "Placing order for items: [{ product: 'laptop', qty: 1 }]"</span>
</code></pre>
<p>This code demonstrates how each microservice is built to handle certain operations, allowing them to work together in a coordinated fashion via an orchestrator service, <code>AmazonService</code>.</p>
<p>The code illustrates the concept of an orchestrated microservices architecture, where each microservice fulfills a unique purpose, such as handling product searches or managing orders, and the orchestrator coordinates these services to create a cohesive interface for the client.</p>
<p>The <code>ProductService</code> class represents a microservice responsible for handling product-related operations, specifically product search. The <code>searchProducts</code> method takes a <code>query</code> parameter, simulating a product search by returning a message that specifies the search query.</p>
<p>This design allows <code>ProductService</code> to be focused on product-related functionality, making it modular and easy to maintain or extend as product search functionality grows more complex.</p>
<p>The <code>OrderService</code> class encapsulates order-related operations. It includes the <code>createOrder</code> method, which accepts an <code>order</code> parameter and returns a message that simulates placing an order.</p>
<p>This method takes advantage of JSON serialization to display the order details in a structured format, showing how each order can be individually managed within <code>OrderService</code>.</p>
<p>By isolating order management functions in their own service, this design makes it possible to scale and maintain order-specific logic without impacting other parts of the application.</p>
<p><code>AmazonService</code> is an orchestrator that coordinates the operations of the <code>ProductService</code> and <code>OrderService</code> classes. In the constructor, instances of <code>ProductService</code> and <code>OrderService</code> are created and stored as properties, allowing <code>AmazonService</code> to call their methods and aggregate their functionalities.</p>
<p>The <code>searchProducts</code> method in <code>AmazonService</code> invokes <code>searchProducts</code> on <code>productService</code>, while the <code>placeOrder</code> method uses <code>createOrder</code> on <code>orderService</code>. This orchestrator provides a simplified interface that abstracts the complexity of the underlying microservices.</p>
<p>The above example shows how <code>AmazonService</code> streamlines client interactions by acting as a single point of access that conceals each microservice's implementation specifics.</p>
<p>This setup demonstrates the modularity and scalability of an orchestrated microservices architecture. Each microservice can be developed, maintained, and scaled independently, while <code>AmazonService</code> coordinates them into a streamlined workflow for the client.</p>
<p>This architecture is especially beneficial in complex applications, such as e-commerce platforms, where each service can focus on its specific domain, ensuring a robust, flexible, and manageable system.</p>
<p>Amazon’s services are decoupled, enabling teams to work on different features independently.</p>
<p>For example, updates to the product search system don’t affect order processing, which improves agility and resilience.</p>
<h3 id="heading-3-uber-managing-rides-drivers-and-payments"><strong>3. Uber: Managing Rides, Drivers, and Payments</strong></h3>
<p>Uber's platform heavily relies on microservices to support its real-time operations, including ride requests, driver matching, fare calculation, and payment processing.</p>
<p>Microservices allow Uber to efficiently scale its system across cities and countries, supporting millions of users simultaneously.</p>
<h4 id="heading-key-microservices-at-uber"><strong>Key Microservices at Uber</strong></h4>
<ul>
<li><p><strong>Request Service</strong>: Manages ride requests from users.</p>
</li>
<li><p><strong>Driver Service</strong>: Matches users with drivers in real-time.</p>
</li>
<li><p><strong>Payment Service</strong>: Handles fare calculations and payment processing.</p>
</li>
</ul>
<p><strong>Conceptual Example: Uber Microservice</strong></p>
<pre><code class="lang-javascript"><span class="hljs-comment">// Request service microservice responsible for creating ride requests</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RequestService</span> </span>{
  createRequest(userId, location) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Creating ride request for user: <span class="hljs-subst">${userId}</span> at location: <span class="hljs-subst">${location}</span>`</span>;
  }
}

<span class="hljs-comment">// Driver service microservice responsible for matching drivers to requests</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DriverService</span> </span>{
  matchDriver(requestId) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Matching driver for request ID: <span class="hljs-subst">${requestId}</span>`</span>;
  }
}

<span class="hljs-comment">// Payment service microservice responsible for processing payments</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentService</span> </span>{
  processPayment(paymentInfo) {
    <span class="hljs-keyword">return</span> <span class="hljs-string">`Processing payment: <span class="hljs-subst">${<span class="hljs-built_in">JSON</span>.stringify(paymentInfo)}</span>`</span>;
  }
}

<span class="hljs-comment">// UberService acting as an orchestrator</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UberService</span> </span>{
  <span class="hljs-keyword">constructor</span>() {
    <span class="hljs-built_in">this</span>.requestService = <span class="hljs-keyword">new</span> RequestService();
    <span class="hljs-built_in">this</span>.driverService = <span class="hljs-keyword">new</span> DriverService();
    <span class="hljs-built_in">this</span>.paymentService = <span class="hljs-keyword">new</span> PaymentService();
  }

  requestRide(userId, location) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.requestService.createRequest(userId, location);
  }

  matchDriver(requestId) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.driverService.matchDriver(requestId);
  }

  processPayment(paymentInfo) {
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.paymentService.processPayment(paymentInfo);
  }
}

<span class="hljs-comment">// Example usage</span>
<span class="hljs-keyword">const</span> uber = <span class="hljs-keyword">new</span> UberService();
<span class="hljs-built_in">console</span>.log(uber.requestRide(<span class="hljs-number">301</span>, <span class="hljs-string">'Downtown'</span>)); <span class="hljs-comment">// "Creating ride request for user: 301 at location: Downtown"</span>
<span class="hljs-built_in">console</span>.log(uber.matchDriver(<span class="hljs-number">401</span>)); <span class="hljs-comment">// "Matching driver for request ID: 401"</span>
<span class="hljs-built_in">console</span>.log(uber.processPayment({ <span class="hljs-attr">amount</span>: <span class="hljs-number">20</span>, <span class="hljs-attr">method</span>: <span class="hljs-string">'Credit Card'</span> })); <span class="hljs-comment">// "Processing payment: { amount: 20, method: 'Credit Card' }"</span>
</code></pre>
<p>You can see how each service in this code represents a unique step in the ride-hailing process, allowing each microservice to handle a specific operation in the flow, from creating ride requests to matching drivers and processing payments. This setup follows the microservice architecture pattern, where each service encapsulates a unique piece of business logic.</p>
<p>By defining these services separately, the code improves maintainability and scalability, as each service can operate independently and be scaled based on specific demands, such as more driver matches or payment processing.</p>
<p>The <code>RequestService</code> class represents a microservice dedicated to handling ride requests from users. It includes the <code>createRequest</code> method, which takes a <code>userId</code> and a <code>location</code> as input parameters.</p>
<p>This method simulates the process of creating a ride request by returning a message that contains both the user’s ID and the specified location. This service isolates the ride-request logic, allowing it to be managed independently of other processes, such as driver matching or payment processing.</p>
<p>The <code>DriverService</code> class encapsulates the logic for finding available drivers for ride requests. It includes a <code>matchDriver</code> method that takes a <code>requestId</code> as input, representing a specific ride request.</p>
<p>The method simulates the driver-matching process by returning a message that includes the request ID. By isolating this functionality, <code>DriverService</code> can be scaled or enhanced as needed without impacting other services, such as the request or payment services.</p>
<p>The <code>PaymentService</code> class is responsible for handling payment transactions. Its <code>processPayment</code> method takes <code>paymentInfo</code> as an input, which includes payment details such as the amount and payment method.</p>
<p>This method returns a message that simulates the payment processing operation, with <code>JSON.stringify(paymentInfo)</code> formatting the payment information as a JSON string for clarity. This approach isolates payment logic, ensuring security and ease of maintenance, as it operates independently from the ride request and driver services.</p>
<p>The <code>UberService</code> class serves as an orchestrator, coordinating the functionality of <code>RequestService</code>, <code>DriverService</code>, and <code>PaymentService</code>. In its constructor, it initializes instances of each service and assigns them to properties, allowing <code>UberService</code> to interact with these services easily.</p>
<p>The <code>requestRide</code> method calls <code>createRequest</code> on <code>requestService</code> to initiate a ride request, while <code>matchDriver</code> and <code>processPayment</code> invoke the respective methods on <code>driverService</code> and <code>paymentService</code>. This orchestration provides a simplified interface for clients by abstracting the implementation details of each microservice.</p>
<p>This example demonstrates how an orchestrated microservice architecture allows for separation of concerns, where each service manages a unique part of the business logic while the orchestrator unifies them into a cohesive API.</p>
<p>This design supports flexibility, scalability, and ease of maintenance, as each service can evolve independently based on business requirements. For instance, the <code>DriverService</code> could be enhanced with more sophisticated driver-matching algorithms without affecting other services, while the <code>PaymentService</code> could be scaled independently to handle high transaction volumes.</p>
<p>Uber’s microservices architecture allows them to handle spikes in demand (such as during rush hour or bad weather) by independently scaling their ride request service, driver matching service, and payment service as needed.</p>
<h3 id="heading-benefits-of-using-microservices-in-these-companies"><strong>Benefits of Using Microservices in These Companies</strong></h3>
<ul>
<li><p><strong>Scalability</strong>: Each microservice can be scaled individually based on demand.<br>  For example, Netflix can scale its streaming service more aggressively than its recommendation service during peak hours.</p>
</li>
<li><p><strong>Fault Isolation</strong>: If one microservice fails (for example, Uber’s payment service), it doesn’t affect the other services like ride requests or driver matching.</p>
</li>
<li><p><strong>Flexibility</strong>: Microservices enable teams to work independently on different parts of the system.<br>  Amazon can develop new features for its product search without touching the order or customer service modules.</p>
</li>
<li><p><strong>Technology Diversity</strong>: Different microservices can be developed using the best technology for the job. For instance, Uber might use Node.js for their real-time driver matching service and Python for their data-heavy analytics services.</p>
</li>
</ul>
<h2 id="heading-common-pitfalls-and-how-to-avoid-them-in-microservices"><strong>Common Pitfalls and How to Avoid Them in Microservices</strong></h2>
<p>While microservices offer significant benefits, they also come with complexities that can lead to failure if not properly managed.</p>
<p>Here, we will discuss and recap (based on what we’ve already covered earlier on) some common pitfalls that organizations face when adopting microservices, provide examples of failed projects, and offer strategies to avoid these issues.</p>
<h3 id="heading-1-overcomplicating-the-architecture-too-early"><strong>1. Overcomplicating the Architecture Too Early</strong></h3>
<p><strong>Pitfall</strong>: One of the most common mistakes companies make when transitioning to microservices is breaking down the system into too many services prematurely.<br>This results in an overly complex architecture that is hard to manage and maintain.</p>
<p><strong>Example of Failure</strong>:</p>
<p>A large-scale retailer attempted to move its entire e-commerce platform from a monolithic architecture to microservices overnight.</p>
<p>The result was a sprawling number of poorly defined services, with no clear ownership, leading to miscommunication between teams and inconsistent data.</p>
<p>This severely hampered performance, leading to a complete rollback to their monolithic architecture.</p>
<p><strong>How to Avoid It</strong>:</p>
<ul>
<li><p><strong>Start Small</strong>: Begin by breaking down only a few core components into microservices, such as user authentication or product search.</p>
</li>
<li><p><strong>Gradual Decomposition</strong>: Use patterns like the <strong>Strangler Fig</strong> to incrementally refactor a monolith into microservices.</p>
</li>
<li><p><strong>Define Service Boundaries</strong>: Make sure you understand the bounded context of each service. Don’t split services until you’re clear about their responsibilities.</p>
</li>
</ul>
<h3 id="heading-2-lack-of-proper-service-ownership"><strong>2. Lack of Proper Service Ownership</strong></h3>
<p><strong>Pitfall</strong>: Without clear ownership of individual microservices, it's easy for problems to arise, such as uncoordinated updates, duplicated efforts, and insufficient monitoring.</p>
<p>This can also cause confusion regarding which team is responsible for the health and performance of specific services.</p>
<p><strong>Example of Failure</strong>:</p>
<p>A major online platform divided its application into hundreds of microservices but failed to assign proper ownership.</p>
<p>This resulted in deployment delays, as it was unclear who was responsible for maintaining and scaling each service, and some services became neglected.</p>
<p>Bugs were not addressed quickly, and performance issues worsened.</p>
<p><strong>How to Avoid It</strong>:</p>
<ul>
<li><p><strong>Clear Ownership</strong>: Assign a specific team or individual responsible for each microservice. This team should handle the development, testing, deployment, and maintenance.</p>
</li>
<li><p><strong>Team Autonomy</strong>: Ensure that the teams responsible for the services have the authority to make decisions about their service’s architecture, scaling, and deployment strategy.</p>
</li>
<li><p><strong>Service Registries</strong>: Maintain a registry or catalog of services, including their owners, so there is clear visibility across the organization.</p>
</li>
</ul>
<h3 id="heading-3-poorly-managed-inter-service-communication"><strong>3. Poorly Managed Inter-Service Communication</strong></h3>
<p><strong>Pitfall</strong>: Microservices rely heavily on communication over the network, making them vulnerable to issues like high latency, network failures, and over-complicated APIs.</p>
<p>Without proper design, inter-service communication can lead to bottlenecks and increase the risk of cascading failures.</p>
<p><strong>Example of Failure</strong>:</p>
<p>A financial services company implemented microservices but failed to plan for efficient inter-service communication.</p>
<p>They used synchronous API calls (REST) extensively, and as the number of services grew, response times degraded significantly.</p>
<p>In addition, when one critical service went down, it caused a cascading failure across the entire system.</p>
<p><strong>How to Avoid It</strong>:</p>
<ul>
<li><p><strong>Use Asynchronous Communication</strong>: Wherever possible, use asynchronous messaging (for example, using message queues like Kafka or RabbitMQ) to avoid tight coupling between services.</p>
</li>
<li><p><strong>Implement Circuit Breakers</strong>: Use circuit breaker patterns to prevent cascading failures. If one service fails, the breaker trips, allowing other services to continue operating independently.</p>
</li>
<li><p><strong>Retry Logic and Timeouts</strong>: Include retry mechanisms and appropriate timeouts in inter-service communication to handle transient failures.</p>
</li>
</ul>
<h3 id="heading-4-ignoring-data-consistency-and-transactions"><strong>4. Ignoring Data Consistency and Transactions</strong></h3>
<p><strong>Pitfall</strong>: In a monolithic architecture, transactions are often straightforward. In microservices, maintaining consistency across distributed services can be difficult, especially when transactions span multiple services.</p>
<p>Ignoring this complexity can lead to data inconsistencies, such as duplicated or missing records.</p>
<p><strong>Example of Failure</strong>:</p>
<p>A payments platform that adopted microservices faced issues where transactions between its order management and payment services would fail midway.</p>
<p>For instance, payments were processed, but the order was not placed due to a network failure.</p>
<p>This inconsistency damaged customer trust and led to costly chargebacks.</p>
<p><strong>How to Avoid It</strong>:</p>
<ul>
<li><p><strong>Use Sagas</strong>: Implement the <strong>Saga pattern</strong> for long-running transactions across multiple services.<br>  This ensures that each service commits or rolls back its part of the transaction independently.</p>
</li>
<li><p><strong>Eventual Consistency</strong>: Accept that not all data will be consistent in real-time.<br>  Use event-driven approaches to ensure that services eventually synchronize their data, which is suitable for many business cases.</p>
</li>
<li><p><strong>Compensating Transactions</strong>: In the event of failure, ensure that services can roll back any changes made in a transaction through compensating transactions.</p>
</li>
</ul>
<h3 id="heading-5-lack-of-monitoring-logging-and-observability"><strong>5. Lack of Monitoring, Logging, and Observability</strong></h3>
<p><strong>Pitfall</strong>: With multiple services running independently, it becomes difficult to track the overall health of the system if there is no central monitoring or logging.</p>
<p>A lack of observability makes it nearly impossible to diagnose issues, detect bottlenecks, or trace failures in production.</p>
<p><strong>Example of Failure</strong>:</p>
<p>An e-commerce platform switched to microservices but lacked a unified logging and monitoring strategy.</p>
<p>When performance issues arose during a major sales event, they couldn’t pinpoint the failing services in time, leading to downtime and lost revenue.</p>
<p><strong>How to Avoid It</strong>:</p>
<ul>
<li><p><strong>Centralized Logging</strong>: Use tools like the <strong>ELK stack (Elasticsearch, Logstash, and Kibana)</strong> or <strong>Fluentd</strong> to collect and centralize logs across all services.</p>
</li>
<li><p><strong>Distributed Tracing</strong>: Implement distributed tracing tools like <strong>Jaeger</strong> or <strong>Zipkin</strong> to trace requests across services, helping to quickly identify bottlenecks.</p>
</li>
<li><p><strong>Monitoring Tools</strong>: Use monitoring and alerting systems such as <strong>Prometheus</strong> and <strong>Grafana</strong> to get real-time insights into service health and performance.</p>
</li>
</ul>
<h3 id="heading-6-security-vulnerabilities-in-microservices"><strong>6. Security Vulnerabilities in Microservices</strong></h3>
<p><strong>Pitfall</strong>: The decentralized nature of microservices introduces new security challenges, including securing API endpoints, managing inter-service communication, and preventing unauthorized access to sensitive data.</p>
<p><strong>Example of Failure</strong>:</p>
<p>A ride-sharing company built a microservices architecture but failed to secure inter-service communication properly.</p>
<p>An attacker was able to exploit an insecure API to access customer data, resulting in a major data breach and damage to the company's reputation.</p>
<p><strong>How to Avoid It</strong>:</p>
<ul>
<li><p><strong>Secure APIs</strong>: Use secure tokens (for example, <strong>OAuth 2.0</strong> or <strong>JWT</strong>) for authenticating and authorizing API requests.</p>
</li>
<li><p><strong>Mutual TLS (mTLS)</strong>: Ensure all communication between services is encrypted by implementing mTLS.</p>
</li>
<li><p><strong>Network Security</strong>: Use virtual private clouds (VPCs), firewalls, and secure access controls to limit who and what can access your services.</p>
</li>
<li><p><strong>Regular Audits</strong>: Ensure compliance with data protection regulations such as <strong>GDPR</strong> or <strong>HIPAA</strong> through regular security audits and testing.</p>
</li>
</ul>
<h3 id="heading-strategies-to-address-and-avoid-common-issues"><strong>Strategies to Address and Avoid Common Issues</strong></h3>
<ol>
<li><p><strong>Adopt an Incremental Approach</strong>: Move to microservices gradually, rather than in one big shift. Start with non-critical services and build expertise.</p>
</li>
<li><p><strong>Service Contracts and APIs</strong>: Ensure that your APIs and contracts between services are well-documented and stable. Changes should be versioned to avoid breaking dependencies.</p>
</li>
<li><p><strong>Use Proper Orchestration Tools</strong>: Utilize container orchestration tools like <strong>Kubernetes</strong> to manage the deployment, scaling, and operation of services.<br> <strong>Service Meshes</strong> like <a target="_blank" href="https://istio.io/"><strong>Istio</strong></a> can handle networking complexities.</p>
</li>
<li><p><strong>Emphasize DevOps and CI/CD</strong>: Implement <strong>CI/CD pipelines</strong> with automated testing and monitoring.<br> Microservices should be easy to deploy frequently and with minimal risk.</p>
</li>
<li><p><strong>Strong Team Collaboration</strong>: Foster a culture of collaboration between development and operations teams.<br> Break down silos and ensure everyone understands how services interact.</p>
</li>
</ol>
<p>Microservices architecture, as demonstrated by companies like Netflix, Amazon, and Uber, showcases the immense potential for scalability, flexibility, and innovation.</p>
<p>Each of these organizations effectively leveraged microservices to enhance their core operations—whether it's delivering content, managing vast product catalogs, or facilitating ride-sharing.</p>
<p>These examples highlight how breaking down applications into independent services empowers teams to deploy faster, scale efficiently, and innovate rapidly.</p>
<p>But the journey to a successful microservices architecture is not without its challenges.</p>
<p>Common pitfalls, such as overcomplicating the architecture, poor service ownership, and unreliable inter-service communication, can derail even the most well-intentioned projects.</p>
<p>To avoid these issues, it’s essential to start small, establish clear service boundaries, adopt asynchronous communication, and implement robust monitoring and security measures.</p>
<p>By learning from real-world successes and failures, and implementing strategies to mitigate common risks, organizations can fully unlock the potential of microservices while maintaining operational stability, security, and performance.</p>
<p>Proper planning, gradual adoption, and continuous monitoring are key to building a resilient and scalable microservices-based system.</p>
<h2 id="heading-future-trends-and-innovations">Future Trends and Innovations</h2>
<p>In this section, we will discuss some cutting-edge developments and emerging trends that are shaping the future of microservices architecture. This section will examine the impact of new technologies and methodologies, such as serverless computing, micro frontends, and the use of AI-driven automation in service orchestration and management.</p>
<p>We’ll also look at the evolving role of DevOps and continuous integration/continuous delivery (CI/CD) pipelines in enhancing microservices deployment and maintenance.</p>
<p>Then we’ll discuss advancements in service mesh technologies, the increasing importance of observability and monitoring tools, and the rise of event-driven architecture as a complement to traditional request-response communication in microservices.</p>
<p>By the end of this section, you’ll gain insights into how these innovations are pushing microservices architecture forward, helping organizations further streamline, scale, and optimize their applications.</p>
<p>This forward-looking view will equip you with knowledge on potential tools and strategies that can keep your applications competitive and adaptable in a rapidly changing technological landscape.</p>
<h3 id="heading-serverless-architecture">Serverless Architecture</h3>
<p>Serverless architecture allows you to build and run applications without managing servers.</p>
<p>Functions are executed in response to events, and resources are automatically scaled based on demand.</p>
<p>Imagine a coffee shop where you order coffee through an app. The coffee shop only needs to prepare coffee when an order is placed, and you don’t need to worry about the kitchen staff or equipment.</p>
<h5 id="heading-aws-lambda-function">AWS Lambda Function:</h5>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example of an AWS Lambda function</span>
<span class="hljs-built_in">exports</span>.handler = <span class="hljs-keyword">async</span> (event) =&gt; {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Event received:'</span>, event);
  <span class="hljs-comment">// Process the event and return a response</span>
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">statusCode</span>: <span class="hljs-number">200</span>,
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">message</span>: <span class="hljs-string">'Hello from Lambda!'</span> }),
  };
};
</code></pre>
<p>This code depicts how an AWS Lambda function is defined to handle and process events. AWS Lambda is a serverless compute service that allows you to run code without provisioning or managing servers.</p>
<p>In this code example, the function is set up to run in response to an event—whether that’s an HTTP request, an update in a data source, or any other event that can trigger a Lambda function.</p>
<p>The function's entry point is the <code>exports.handler</code>, which is structured as an asynchronous function with an <code>event</code> parameter. This <code>event</code> parameter contains the data relevant to the trigger, like request details if invoked through API Gateway or object information if triggered by S3.</p>
<p>The <code>console.log('Event received:', event);</code> line logs the event data to AWS CloudWatch, which is useful for debugging and tracking the input data Lambda received. This log output helps monitor and troubleshoot the function's operation and behavior by examining the event data and ensuring it is processed as expected.</p>
<p>Following the logging statement, the code returns a response object. Here, it returns an object with <code>statusCode</code> set to <code>200</code>, indicating a successful request, and a <code>body</code> field containing a JSON stringified message. This JSON message (<code>{ message: 'Hello from Lambda!' }</code>) is typical for RESTful APIs and provides a response payload that a client can interpret.</p>
<p>The <code>statusCode</code> and <code>body</code> fields are crucial when the Lambda function is integrated with API Gateway, as they enable Lambda to respond to HTTP requests in a format that is directly consumable by web clients or applications.</p>
<p>This example shows how Lambda functions can perform a wide range of tasks triggered by various events, making them suitable for microservices and scalable cloud applications where functions execute code only when invoked, minimizing costs and resource usage.</p>
<p>The use of asynchronous processing (<code>async</code>) allows the function to handle any potential network or data-fetching tasks non-blockingly, which is ideal for serverless environments where efficiency and quick execution are prioritized.</p>
<h5 id="heading-benefits-and-challenges"><strong>Benefits and Challenges:</strong></h5>
<ul>
<li><p><strong>Benefits:</strong> Reduced infrastructure management, automatic scaling, and pay-per-use pricing.</p>
</li>
<li><p><strong>Challenges:</strong> Cold start latency, limited execution time, and complexity in debugging and monitoring.</p>
</li>
</ul>
<p>It’s like ordering takeout from a restaurant—convenient and flexible, but you rely on the restaurant’s setup and might have to wait if they’re busy.</p>
<h5 id="heading-future-directions"><strong>Future Directions:</strong></h5>
<ul>
<li><p><strong>Improved Cold Start Times:</strong> Techniques to reduce latency for serverless functions.</p>
</li>
<li><p><strong>Enhanced Monitoring and Debugging:</strong> Better tools for tracking and debugging serverless applications.</p>
</li>
</ul>
<h3 id="heading-service-meshes">Service Meshes</h3>
<p>A service mesh is an infrastructure layer that provides features like service-to-service communication, load balancing, and security for microservices.</p>
<p>Think of a service mesh as a network of interconnected communication channels within a company, ensuring secure and efficient data flow between departments.</p>
<h5 id="heading-conceptual-with-istio">Conceptual with Istio:</h5>
<pre><code class="lang-yaml"><span class="hljs-comment"># Example of an Istio VirtualService configuration</span>
<span class="hljs-attr">apiVersion:</span> <span class="hljs-string">networking.istio.io/v1beta1</span>
<span class="hljs-attr">kind:</span> <span class="hljs-string">VirtualService</span>
<span class="hljs-attr">metadata:</span>
  <span class="hljs-attr">name:</span> <span class="hljs-string">example-virtualservice</span>
<span class="hljs-attr">spec:</span>
  <span class="hljs-attr">hosts:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-string">example-service</span>
  <span class="hljs-attr">http:</span>
    <span class="hljs-bullet">-</span> <span class="hljs-attr">route:</span>
        <span class="hljs-bullet">-</span> <span class="hljs-attr">destination:</span>
            <span class="hljs-attr">host:</span> <span class="hljs-string">example-service</span>
            <span class="hljs-attr">port:</span>
              <span class="hljs-attr">number:</span> <span class="hljs-number">80</span>
</code></pre>
<p>In this code, you can see how Istio’s <strong>VirtualService</strong> configuration is used to define the routing of HTTP traffic within a microservices architecture. Istio is a popular service mesh that helps manage microservices traffic, security, and observability in a Kubernetes environment.</p>
<p>A <strong>VirtualService</strong> is one of Istio’s core components and is used to control how traffic is directed to specific services within the mesh.</p>
<p>The configuration starts with the <code>apiVersion</code> and <code>kind</code> fields, which specify that this is an Istio <code>VirtualService</code> resource and the API version used to define it. The <code>metadata</code> section gives the virtual service a name, <code>example-virtualservice</code>, which can be used to reference it within the Istio mesh.</p>
<p>The <code>spec</code> section defines the main functionality of the VirtualService. The <code>hosts</code> field lists the services that this VirtualService applies to—in this case, it specifies a service called <code>example-service</code>.</p>
<p>This is the destination for the traffic that matches the routing rules defined within this VirtualService.</p>
<p>In the <code>http</code> section, we define how HTTP traffic should be routed. The <code>route</code> field specifies that requests to the <code>example-service</code> should be forwarded to the host <code>example-service</code> on port 80.</p>
<p>This is a basic routing rule where all incoming HTTP traffic that matches the <code>example-service</code> will be directed to the service on port 80. More complex routing rules could be added here, such as load balancing between multiple instances of a service, routing based on request headers, or applying retries and timeouts.</p>
<p>This example is a simple yet powerful demonstration of Istio’s traffic management capabilities. Istio enables fine-grained control over how microservices communicate with each other, making it possible to implement advanced traffic routing strategies such as A/B testing, blue-green deployments, and canary releases.</p>
<h5 id="heading-benefits-and-challenges-1"><strong>Benefits and Challenges:</strong></h5>
<ul>
<li><p><strong>Benefits:</strong> Simplified communication management, security, and observability.</p>
</li>
<li><p><strong>Challenges:</strong> Additional complexity in setup and management.</p>
</li>
</ul>
<p>It’s like using a company-wide intranet to manage internal communication, which adds layers of control but requires proper setup.</p>
<h5 id="heading-future-directions-1"><strong>Future Directions:</strong></h5>
<ul>
<li><p><strong>Better Integration with CI/CD:</strong> Improved integration of service meshes with continuous integration and deployment pipelines.</p>
</li>
<li><p><strong>Advanced Security Features:</strong> Enhanced mechanisms for securing service-to-service communication.</p>
</li>
</ul>
<h3 id="heading-artificial-intelligence-and-machine-learning-integration"><strong>Artificial Intelligence and Machine Learning Integration</strong></h3>
<p>Incorporating AI and machine learning into microservices to enable predictive analytics, automation, and intelligent decision-making.</p>
<p>It’s like adding a personal assistant to your team that can analyze data and provide recommendations or automate repetitive tasks.</p>
<h5 id="heading-using-tensorflowjs"><strong>Using TensorFlow.js:</strong></h5>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> tf = <span class="hljs-built_in">require</span>(<span class="hljs-string">'@tensorflow/tfjs'</span>);

<span class="hljs-comment">// Define a simple model</span>
<span class="hljs-keyword">const</span> model = tf.sequential();
model.add(tf.layers.dense({ <span class="hljs-attr">units</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">inputShape</span>: [<span class="hljs-number">1</span>] }));

model.compile({ <span class="hljs-attr">optimizer</span>: <span class="hljs-string">'sgd'</span>, <span class="hljs-attr">loss</span>: <span class="hljs-string">'meanSquaredError'</span> });

<span class="hljs-comment">// Training data</span>
<span class="hljs-keyword">const</span> xs = tf.tensor1d([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]);
<span class="hljs-keyword">const</span> ys = tf.tensor1d([<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">7</span>]);

<span class="hljs-comment">// Train the model</span>
model.fit(xs, ys, { <span class="hljs-attr">epochs</span>: <span class="hljs-number">10</span> }).then(<span class="hljs-function">() =&gt;</span> {
  model.predict(tf.tensor1d([<span class="hljs-number">5</span>])).print(); <span class="hljs-comment">// Predict new values</span>
});
</code></pre>
<p>The above example demonstrates how TensorFlow.js is used to define and train a simple machine learning model in Javascript. TensorFlow.js is a popular library that allows you to train and deploy machine learning models directly in the browser or in Node.js environments.</p>
<p>This example demonstrates how to create a model, train it with some data, and make predictions using that model.</p>
<p>The first line imports the TensorFlow.js library (<code>const tf = require('@tensorflow/tfjs');</code>), making its functionality available for use in this script. TensorFlow.js provides a rich set of APIs for building, training, and evaluating machine learning models.</p>
<p>The code then proceeds to define a simple machine learning model using the <code>tf.sequential()</code> function, which creates a linear stack of layers. This is a simple model composed of a single layer: a dense layer (<code>tf.layers.dense</code>). The dense layer has 1 unit and expects an input shape of 1, meaning it will take in a single numeric input per training sample.</p>
<p>Once the model structure is defined, it is compiled with the <code>model.compile()</code> method. This step sets up the model for training by specifying the optimizer and loss function. The <code>optimizer: 'sgd'</code> indicates that <strong>stochastic gradient descent (SGD)</strong> will be used to update the model's weights during training.</p>
<p>The <code>loss: 'meanSquaredError'</code> specifies that the model will minimize the mean squared error (MSE) during training, which is commonly used for regression tasks (where the goal is to predict continuous values).</p>
<p>Next, the training data is defined. The input data (<code>xs</code>) is a 1-dimensional tensor with the values <code>[1, 2, 3, 4]</code>, and the target output data (<code>ys</code>) is another tensor with the corresponding values <code>[1, 3, 5, 7]</code>. This dataset suggests a simple linear relationship: <code>y = 2x - 1</code>.</p>
<p>The model is trained using the <code>model.fit()</code> function. This method takes in the training data (<code>xs</code>, <code>ys</code>) and the number of epochs (iterations) to train for. In this case, the model is trained for 10 epochs. During each epoch, the model updates its internal weights to minimize the loss function (mean squared error). After training, the model is capable of making predictions.</p>
<p>Finally, after the model is trained, the <code>model.predict()</code> function is called with new input data (<code>tf.tensor1d([5])</code>). This predicts the output for an unseen input (in this case, <code>x = 5</code>). The <code>print()</code> method is used to display the predicted result.</p>
<p>Through this code, you can see how <strong>TensorFlow.js</strong> provides an easy and flexible way to create, train, and use machine learning models in JavaScript.</p>
<p>The model here performs a simple linear regression, but TensorFlow.js can be used to tackle much more complex tasks, including deep learning and neural networks, in both the browser and server-side environments.</p>
<h5 id="heading-benefits-and-challenges-2"><strong>Benefits and Challenges:</strong></h5>
<ul>
<li><p><strong>Benefits:</strong> Enhanced capabilities such as predictive analytics, automation, and personalized user experiences.</p>
</li>
<li><p><strong>Challenges:</strong> Complexity in integrating AI/ML models, and the need for large datasets and computational resources.</p>
</li>
</ul>
<p>It’s like hiring a data scientist who can provide insights and automate processes but requires careful integration and resources.</p>
<h5 id="heading-future-directions-2"><strong>Future Directions:</strong></h5>
<ul>
<li><p><strong>Increased Use of AutoML:</strong> Simplified processes for training and deploying machine learning models.</p>
</li>
<li><p><strong>More Advanced AI Models:</strong> Incorporation of more sophisticated models and techniques for various use cases.</p>
</li>
</ul>
<h3 id="heading-edge-computing"><strong>Edge Computing</strong></h3>
<p>Edge computing involves processing data closer to the data source (for example, IoT devices) rather than relying solely on centralized cloud servers.</p>
<p>Like having a local technician who can handle immediate issues on-site rather than sending everything to a central repair facility.</p>
<h5 id="heading-benefits-and-challenges-3"><strong>Benefits and Challenges:</strong></h5>
<ul>
<li><p><strong>Benefits:</strong> Reduced latency, improved performance, and decreased bandwidth usage.</p>
</li>
<li><p><strong>Challenges:</strong> Complexity in managing distributed edge devices and ensuring data consistency.</p>
</li>
</ul>
<p>It’s like managing multiple local warehouses to reduce shipping times, but requiring coordination and consistency.</p>
<h5 id="heading-future-directions-3"><strong>Future Directions:</strong></h5>
<ul>
<li><p><strong>More Advanced Edge Devices:</strong> Development of more powerful and intelligent edge devices.</p>
</li>
<li><p><strong>Improved Data Management:</strong> Enhanced tools for managing and syncing data across edge and central systems.</p>
</li>
</ul>
<h3 id="heading-enhanced-security-practices"><strong>Enhanced Security Practices</strong></h3>
<p>Implementation of advanced security practices such as zero-trust models, encryption, and secure APIs to protect microservices.</p>
<p>It’s like having a comprehensive security system with surveillance, access control, and encryption to protect your premises and data.</p>
<h5 id="heading-using-crypto-for-encryption"><strong>Using Crypto for Encryption:</strong></h5>
<pre><code class="lang-javascript"><span class="hljs-keyword">const</span> crypto = <span class="hljs-built_in">require</span>(<span class="hljs-string">'crypto'</span>);

<span class="hljs-comment">// Encrypt data</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">encrypt</span>(<span class="hljs-params">text</span>) </span>{
  <span class="hljs-keyword">const</span> cipher = crypto.createCipher(<span class="hljs-string">'aes-256-cbc'</span>, <span class="hljs-string">'password'</span>);
  <span class="hljs-keyword">let</span> encrypted = cipher.update(text, <span class="hljs-string">'utf8'</span>, <span class="hljs-string">'hex'</span>);
  encrypted += cipher.final(<span class="hljs-string">'hex'</span>);
  <span class="hljs-keyword">return</span> encrypted;
}

<span class="hljs-comment">// Decrypt data</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">decrypt</span>(<span class="hljs-params">text</span>) </span>{
  <span class="hljs-keyword">const</span> decipher = crypto.createDecipher(<span class="hljs-string">'aes-256-cbc'</span>, <span class="hljs-string">'password'</span>);
  <span class="hljs-keyword">let</span> decrypted = decipher.update(text, <span class="hljs-string">'hex'</span>, <span class="hljs-string">'utf8'</span>);
  decrypted += decipher.final(<span class="hljs-string">'utf8'</span>);
  <span class="hljs-keyword">return</span> decrypted;
}

<span class="hljs-keyword">const</span> text = <span class="hljs-string">'Hello World'</span>;
<span class="hljs-keyword">const</span> encryptedText = encrypt(text);
<span class="hljs-keyword">const</span> decryptedText = decrypt(encryptedText);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Encrypted:'</span>, encryptedText);
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Decrypted:'</span>, decryptedText);
</code></pre>
<p>This code exhibits how encryption and decryption are implemented in Node.js using the <code>crypto</code> module, which provides a variety of cryptographic functionality, including hashing, signing, and encryption.</p>
<p>The encryption used here follows the <strong>AES-256-CBC</strong> algorithm, which is a widely used symmetric encryption algorithm. This means that the same key is used for both encryption and decryption.</p>
<p>The <code>encrypt()</code> function demonstrates the process of <strong>encrypting</strong> a plain text message. It first creates a cipher instance using the <code>crypto.createCipher()</code> method, specifying <code>aes-256-cbc</code> as the encryption algorithm and <code>'password'</code> as the encryption key. The <code>createCipher()</code> method returns a cipher object that is used to process the text.</p>
<p>The encryption process is done in two stages. First, the <code>cipher.update()</code> method is used to encrypt the input text, in this case <code>'Hello World'</code>. The method takes three arguments: the input text, the encoding of the input text (here it's <code>'utf8'</code>), and the encoding of the output (here it's <code>'hex'</code>).</p>
<p>This means the encrypted text will be output in hexadecimal format. The second part, <a target="_blank" href="http://cipher.final"><code>cipher.final</code></a><code>('hex')</code>, ensures the final padding and encryption are properly applied, returning the complete encrypted text. This encrypted string is returned as the result of the <code>encrypt()</code> function.</p>
<p>The <code>decrypt()</code> function works similarly but in reverse. It starts by creating a decipher instance using <code>crypto.createDecipher()</code>, again specifying <code>'aes-256-cbc'</code> as the algorithm and the same key (<code>'password'</code>).</p>
<p>The <code>decipher.update()</code> method is used to decrypt the data, converting it back from hexadecimal format to UTF-8. As with the encryption function, <a target="_blank" href="http://decipher.final"><code>decipher.final</code></a><code>('utf8')</code> ensures the complete decryption of the data, returning the decrypted string.</p>
<p>In the example, the text <code>'Hello World'</code> is first encrypted and then immediately decrypted. The output demonstrates how the original text is converted into an encrypted format and then restored back to its original form.</p>
<p>The use of <code>'password'</code> as a static key in this example is not secure for real-world applications, but it serves to illustrate the basic encryption and decryption process.</p>
<p>This example also highlights the importance of using strong, unique keys for cryptographic operations in practice, as well as ensuring that encrypted data is safely stored and transmitted.</p>
<p>The <code>crypto</code> module, which is built into Node.js, makes it easy to implement secure encryption and decryption in any application requiring data protection.</p>
<h5 id="heading-benefits-and-challenges-4"><strong>Benefits and Challenges:</strong></h5>
<ul>
<li><p><strong>Benefits:</strong> Enhanced protection against data breaches and cyber-attacks.</p>
</li>
<li><p><strong>Challenges:</strong> Increased complexity in implementation and management.</p>
</li>
</ul>
<p>It’s like upgrading from a basic lock to a high-security system with multiple layers of protection.</p>
<h5 id="heading-future-directions-4"><strong>Future Directions:</strong></h5>
<ul>
<li><p><strong>Zero Trust Architectures:</strong> Increased adoption of zero trust models where verification is required for every request.</p>
</li>
<li><p><strong>Advanced Encryption Techniques:</strong> Continued development of more secure and efficient encryption methods.</p>
</li>
</ul>
<h3 id="heading-multi-cloud-and-hybrid-cloud-strategies"><strong>Multi-Cloud and Hybrid Cloud Strategies</strong></h3>
<p>Using multiple cloud providers (multi-cloud) or combining on-premises infrastructure with cloud services (hybrid cloud) to improve flexibility and avoid vendor lock-in.</p>
<p>It’s like having accounts with multiple banks to take advantage of different services and avoid reliance on a single provider.</p>
<h5 id="heading-conceptual-with-multiple-cloud-providers"><strong>Conceptual with Multiple Cloud Providers:</strong></h5>
<pre><code class="lang-javascript"><span class="hljs-comment">// Example of interacting with multiple cloud providers</span>
<span class="hljs-keyword">const</span> AWS = <span class="hljs-built_in">require</span>(<span class="hljs-string">'aws-sdk'</span>);
<span class="hljs-keyword">const</span> azure = <span class="hljs-built_in">require</span>(<span class="hljs-string">'azure-storage'</span>);

<span class="hljs-comment">// AWS S3 interaction</span>
<span class="hljs-keyword">const</span> s3 = <span class="hljs-keyword">new</span> AWS.S3();
s3.listBuckets(<span class="hljs-function">(<span class="hljs-params">err, data</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (err) <span class="hljs-built_in">console</span>.log(err, err.stack);
  <span class="hljs-keyword">else</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'S3 Buckets:'</span>, data.Buckets);
});

<span class="hljs-comment">// Azure Blob Storage interaction</span>
<span class="hljs-keyword">const</span> blobService = azure.createBlobService();
blobService.listContainers(<span class="hljs-function">(<span class="hljs-params">err, result</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (err) <span class="hljs-built_in">console</span>.log(err);
  <span class="hljs-keyword">else</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Azure Containers:'</span>, result.entries);
});
</code></pre>
<p>This code describes how you can interact with two distinct cloud providers—<strong>AWS</strong> and <strong>Azure</strong>—specifically their storage services. The code demonstrates how to use <strong>AWS S3</strong> and <strong>Azure Blob Storage</strong> APIs to list buckets and containers, respectively.</p>
<p>The first part of the code shows how to interact with <strong>AWS S3</strong>. It imports the <code>aws-sdk</code> package, which is a Node.js SDK that allows applications to interact with AWS services.</p>
<p>A new instance of the <code>S3</code> service is created using <code>new AWS.S3()</code>. The <code>listBuckets()</code> method is then called on the <code>S3</code> instance to retrieve a list of all buckets within the configured AWS account.</p>
<p>This method is asynchronous, so it takes a callback function as an argument. If the operation is successful, the callback logs the list of buckets to the console. If there's an error, the error message is printed instead.</p>
<p>This demonstrates a basic interaction with AWS's S3 service, where you can programmatically access and manage your storage containers (called "buckets").</p>
<p>Next, the code switches to <strong>Azure Blob Storage</strong>. It uses the <code>azure-storage</code> package, which is the official SDK for interacting with Azure's storage services. The <code>createBlobService()</code> method is used to create a blob service client that interacts with Azure Blob Storage.</p>
<p>The <code>listContainers()</code> method is called on the blob service client to list all the containers in the account. As with AWS, this method is asynchronous, and the result is provided via a callback. If successful, the list of containers (stored in the <code>entries</code> property) is logged to the console.</p>
<p>This code shows how developers can integrate with multiple cloud platforms to manage cloud storage resources, using the APIs provided by each service. The primary takeaway is that both AWS and Azure provide SDKs for interacting with their services, making it easy to automate and manage cloud resources programmatically.</p>
<p>These APIs allow you to perform basic tasks such as listing storage containers, which is a common requirement when working with cloud storage solutions. By using these SDKs, applications can remain cloud-agnostic while still leveraging the full power of each platform’s storage offerings.</p>
<h5 id="heading-benefits-and-challenges-5"><strong>Benefits and Challenges:</strong></h5>
<ul>
<li><p><strong>Benefits:</strong> Greater flexibility, reduced risk of vendor lock-in, and optimization of services across providers.</p>
</li>
<li><p><strong>Challenges:</strong> Increased complexity in managing and integrating services across different environments.</p>
</li>
</ul>
<p>It’s like using different suppliers for various needs to get the best deals but requiring careful coordination and management.</p>
<h5 id="heading-future-directions-5"><strong>Future Directions:</strong></h5>
<ul>
<li><p><strong>Improved Integration Tools:</strong> Development of better tools and platforms for managing multi-cloud and hybrid cloud environments.</p>
</li>
<li><p><strong>Advanced Orchestration:</strong> Enhanced orchestration and management capabilities across diverse cloud environments.</p>
</li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The rapid evolution of technology has significantly transformed how applications are built and managed, and microservices have become a central component of this transformation.</p>
<p>Let’s go over the key points we’ve discussed throughout this book. I’ll reinforce the importance of microservices, and provide guidance on how to leverage these insights for future development.</p>
<h3 id="heading-microservices-architecture">Microservices Architecture</h3>
<p>Microservices involve breaking down applications into smaller, independent services that communicate over well-defined APIs.</p>
<p>This contrasts with monolithic architectures, where all components are interwoven into a single, cohesive application.</p>
<p>Key characteristics include independent deployment, decentralized data management, and resilience through the isolation of services.</p>
<h4 id="heading-core-concepts-and-components">Core Concepts and Components</h4>
<ul>
<li><p><strong>Service Discovery:</strong> Mechanisms for locating and interacting with microservices.</p>
</li>
<li><p><strong>API Gateways:</strong> Centralized entry points that manage traffic, enforce security, and handle requests.</p>
</li>
<li><p><strong>Data Management:</strong> Strategies for managing data consistency and storage across distributed services.</p>
</li>
<li><p><strong>Security:</strong> Implementing authentication, authorization, and encryption to protect services.</p>
</li>
<li><p><strong>Monitoring and Logging:</strong> Tools and practices for tracking performance and diagnosing issues.</p>
</li>
</ul>
<h3 id="heading-building-microservices">Building Microservices</h3>
<ul>
<li><p><strong>Design Principles:</strong> Focus on domain-driven design, scalability, and fault tolerance.</p>
</li>
<li><p><strong>Development Practices:</strong> Best practices include using lightweight communication protocols, managing service dependencies carefully, and employing CI/CD pipelines for automation.</p>
</li>
<li><p><strong>Testing Strategies:</strong> Testing microservices involves unit tests, integration tests, and end-to-end tests to ensure robustness and reliability.</p>
</li>
</ul>
<h3 id="heading-managing-microservices-in-the-cloud">Managing Microservices in the Cloud</h3>
<ul>
<li><p><strong>Deployment:</strong> Techniques for deploying microservices, including containerization with Docker and orchestration with Kubernetes.</p>
</li>
<li><p><strong>Service Meshes:</strong> Infrastructure layers that manage service communication, security, and observability.</p>
</li>
<li><p><strong>Configuration Management:</strong> Tools and practices for managing and updating configurations across services.</p>
</li>
</ul>
<h3 id="heading-future-trends-and-innovations-1">Future Trends and Innovations</h3>
<ul>
<li><p><strong>Serverless Architectures:</strong> Enabling scalable and cost-efficient computing by removing server management responsibilities.</p>
</li>
<li><p><strong>Service Meshes:</strong> Enhancing communication and security between microservices.</p>
</li>
<li><p><strong>AI and Machine Learning Integration:</strong> Leveraging advanced analytics and automation within microservices.</p>
</li>
<li><p><strong>Edge Computing:</strong> Bringing processing closer to data sources to reduce latency and improve performance.</p>
</li>
<li><p><strong>Enhanced Security Practices:</strong> Adopting advanced security models and encryption techniques.</p>
</li>
<li><p><strong>Multi-Cloud and Hybrid Cloud Strategies:</strong> Using multiple cloud providers and combining cloud and on-premises infrastructure for flexibility and resilience.</p>
</li>
</ul>
<h3 id="heading-the-importance-of-microservices">The Importance of Microservices</h3>
<p>Microservices offer numerous advantages that align with the demands of modern software development:</p>
<p><strong>Scalability:</strong> Microservices enable horizontal scaling by allowing individual services to scale independently based on demand. This ensures optimal performance and resource utilization.</p>
<ul>
<li>Like expanding a retail store by adding more registers during peak hours without having to rebuild the entire store.</li>
</ul>
<p><strong>Flexibility:</strong> Developers can choose different technologies, frameworks, and languages for different services, enhancing overall flexibility and innovation.</p>
<ul>
<li>Like having different specialists working on various parts of a project, each using the best tools for their specific tasks.</li>
</ul>
<p><strong>Resilience:</strong> By isolating services, failures in one part of the system do not necessarily impact others, improving overall system reliability.</p>
<ul>
<li>Like having a modular power grid where the failure of one line does not disrupt the entire grid.</li>
</ul>
<p><strong>Faster Time-to-Market:</strong> Microservices facilitate continuous integration and continuous delivery (CI/CD) practices, enabling faster development and deployment cycles.</p>
<ul>
<li>Like producing different components of a product simultaneously rather than waiting to assemble everything at once.</li>
</ul>
<h3 id="heading-looking-ahead">Looking Ahead</h3>
<p>As technology continues to evolve, so will the practices and tools related to microservices. Here’s how you can prepare for the future:</p>
<p><strong>Stay Informed:</strong> Keep up with industry trends, new tools, and best practices through continuous learning and professional development.</p>
<ul>
<li><strong>Recommendation:</strong> Follow industry blogs, attend conferences, and participate in relevant workshops.</li>
</ul>
<p><strong>Experiment with Emerging Technologies:</strong> Integrate new trends and innovations such as serverless computing, AI, and edge computing into your microservices architecture to stay ahead of the curve.</p>
<ul>
<li><strong>Recommendation:</strong> Start with small projects or pilot programs to evaluate the benefits and challenges of new technologies.</li>
</ul>
<p><strong>Adopt Agile Practices:</strong> Embrace agile methodologies to enhance collaboration, flexibility, and iterative development, which align well with the principles of microservices.</p>
<ul>
<li><strong>Recommendation:</strong> Implement agile frameworks such as Scrum or Kanban to improve project management and delivery.</li>
</ul>
<p><strong>Focus on Security:</strong> Prioritize security in your microservices architecture to protect against evolving threats and ensure data integrity.</p>
<ul>
<li><strong>Recommendation:</strong> Regularly review and update security practices, and invest in tools and training for secure coding and compliance.</li>
</ul>
<p><strong>Optimize for Performance:</strong> Continuously monitor and optimize the performance of your microservices to ensure they meet user expectations and handle growing demands efficiently.</p>
<ul>
<li><strong>Recommendation:</strong> Use performance monitoring tools and conduct regular performance reviews to identify and address bottlenecks.</li>
</ul>
<h3 id="heading-final-thoughts">Final Thoughts</h3>
<p>Microservices represent a powerful paradigm shift in software architecture, offering significant benefits in terms of scalability, flexibility, and resilience.</p>
<p>However, they also come with challenges that require thoughtful planning and management.</p>
<p>By understanding the core concepts, embracing best practices, and staying abreast of emerging trends, you can effectively leverage microservices to build robust, scalable, and innovative applications.</p>
<p>The journey of adopting and mastering microservices is ongoing. As technology advances, so will the methodologies and tools that support microservices.</p>
<p>Embrace this journey with curiosity and adaptability, and you’ll be well-positioned to harness the full potential of microservices for your projects and organizations.</p>
<h3 id="heading-further-reading-and-resources">Further Reading and Resources</h3>
<p>For those looking to deepen their understanding of microservices, here are some recommended books, articles, courses, and online communities to continue your learning journey:</p>
<h4 id="heading-recommended-books">Recommended Books:</h4>
<ul>
<li><p><a target="_blank" href="https://www.oreilly.com/library/view/building-microservices-2nd/9781492034018/"><strong>"Building Microservices, 2nd Edition" by Sam Newman (2021)</strong></a><strong>:</strong> This updated edition provides practical advice on implementing and scaling microservices architectures. It covers topics like service decomposition, handling complexity, and communication between microservices.</p>
</li>
<li><p><strong>"</strong><a target="_blank" href="https://www.amazon.com/Microservices-Patterns-examples-Chris-Richardson/dp/1617294543"><strong>Microservices Patterns: With examples in Java" by Chris Richardson</strong></a><strong>:</strong> Focuses on patterns and practices for designing and deploying microservices, including key topics like service discovery, event-driven architecture, and Saga pattern.</p>
</li>
</ul>
<h4 id="heading-articles-and-blogs">Articles and Blogs:</h4>
<ul>
<li><p><strong>"The Twelve-Factor App"</strong><br>  This resource lays out the principles of building modern, scalable applications, and many of its ideas are directly applicable to microservices development.</p>
</li>
<li><p><a target="_blank" href="https://www.contentstack.com/blog/composable/the-future-of-microservices-software-trends-in-2024"><strong>“Probing the Future of Microservices: Software Trends in 2024”</strong></a> - Contentstack (2024) This blog provides insights into the latest developments and trends in microservices, including the growing adoption of Kubernetes, AIOps, service meshes, and event-driven architectures.<br>  It highlights the importance of staying updated with these trends for efficient development and deployment.</p>
</li>
<li><p><a target="_blank" href="https://www.redhat.com/en/topics/microservices"><strong>"Understanding Microservices Architecture" by Red Hat</strong></a><strong>:</strong> A detailed breakdown of microservices, with practical examples and case studies for building cloud-native applications.</p>
</li>
</ul>
<h4 id="heading-online-courses">Online Courses:</h4>
<ul>
<li><p><a target="_blank" href="https://www.udemy.com/course/microservices-with-node-js-and-react/"><strong>"Microservices with Node.js</strong></a> <a target="_blank" href="https://www.ecosmob.com/key-microservices-trends/"><strong>and React" by Udemy:</strong></a> A hands-on course focusing on building, testing, and deploying microservices using Node.js and React.</p>
<p>  <a target="_blank" href="https://www.udemy.com/course/building-microservices-with-spring-boot-and-spring-cloud/"><strong>"Building Microservices with Spring Boot &amp; Spring Cloud" - Udemy (2024)</strong></a>: Learn to build REST APIs using Spring Boot, Spring Cloud, Kafka, RabbitMQ, Docker, and more. This course covers how to build microservices, manage inter-service communication, and implement advanced features like circuit breakers and load balancing. It’s updated for the latest Spring Boot 3 and Spring Cloud technologies.</p>
</li>
<li><p><a target="_blank" href="https://www.udemy.com/course/build-scalable-applications-using-docker-and-kubernetes/"><strong>"Building Scalable Microservices with Kubernetes" by Udemy</strong></a><strong>:</strong> Focuses on deploying and managing microservices using Kubernetes, with detailed instructions on containerization, orchestration, and service discovery.</p>
</li>
</ul>
<h4 id="heading-online-communities-and-forums">Online Communities and Forums:</h4>
<ul>
<li><p><a target="_blank" href="https://www.reddit.com/r/microservices/"><strong>Reddit: r/microservices</strong></a><strong>:</strong> A community dedicated to discussions on microservices architecture, design patterns, and implementation challenges. You can find real-world insights and ask questions on various microservices topics.</p>
</li>
<li><p><a target="_blank" href="https://stackoverflow.com/questions/tagged/microservices"><strong>Stack Overflow (Microservices tag)</strong></a><strong>:</strong> One of the largest communities for software developers, offering a vast repository of questions, answers, and discussions about microservices-related issues and solutions.</p>
</li>
<li><p><a target="_blank" href="https://microservices.io/"><strong>Microservices.io Community</strong></a><strong>:</strong> An online forum curated by Chris Richardson, where developers can exchange ideas, best practices, and patterns for building microservices systems.</p>
</li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Linux for Beginners: From Basics to Advanced Techniques [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ Learning Linux is one of the most valuable skills in the tech industry. It can help you get things done faster and more efficiently. Many of the world's powerful servers and supercomputers run on Linux. While empowering you in your current role, lear... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-linux-for-beginners-book-basic-to-advanced/</link>
                <guid isPermaLink="false">66912d3051ed9fa23c06c654</guid>
                
                    <category>
                        <![CDATA[ Linux ]]>
                    </category>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ beginner ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Zaira Hira ]]>
                </dc:creator>
                <pubDate>Fri, 12 Jul 2024 13:18:40 +0000</pubDate>
                <media:content url="https://cdn.hashnode.com/res/hashnode/image/upload/v1720790242560/764782a4-1bf3-45a5-857c-7fe3921bfb08.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Learning Linux is one of the most valuable skills in the tech industry. It can help you get things done faster and more efficiently. Many of the world's powerful servers and supercomputers run on Linux.</p>
<p>While empowering you in your current role, learning Linux can also help you transition into other tech careers like DevOps, Cybersecurity, and Cloud Computing.</p>
<p>In this handbook, you'll learn the basics of the Linux command line, and then transition to more advanced topics like shell scripting and system administration. Whether you are new to Linux or have been using it for years, this book has something for you.</p>
<p>Important Note: All examples in this book are demonstrated in Ubuntu 22.04.2 LTS (Jammy Jellyfish). Most command line tools are more or less the same in other distributions. However, some GUI applications and commands may differ if you are working on another Linux distribution.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><p><a class="post-section-overview" href="#heading-part-1-introduction-to-linux">Part 1: Introduction to Linux</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-11-getting-started-with-linux">1.1. Getting Started with Linux</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-part-2-introduction-to-bash-shell-and-system-commands">Part 2: Introduction to Bash Shell and System Commands</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-21-getting-started-with-the-bash-shell">2.1. Getting Started with the Bash shell</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-22-command-structure">2.2. Command Structure</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-23-bash-commands-and-keyboard-shortcuts">2.3. Bash Commands and Keyboard Shortcuts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-24-identifying-yourself-the-whoami-command">2.4. Identifying Yourself: The <code>whoami</code> Command</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-part-3-understanding-your-linux-system">Part 3: Understanding Your Linux System</a></p>
<ul>
<li><a class="post-section-overview" href="#heading-31-discovering-your-os-and-specs">3.1. Discovering Your OS and Specs</a></li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-part-4-managing-files-from-the-command-line">Part 4: Managing Files From the Command line</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-41-the-linux-file-system-hierarchy">4.1. The Linux File-system Hierarchy</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-42-navigating-the-linux-file-system">4.2. Navigating the Linux File-system</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-43-managing-files-and-directories">4.3. Managing Files and Directories</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-45-basic-commands-for-viewing-files">4.5. Basic Commands for Viewing Files</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-part-5-the-essentials-of-text-editing-in-linux">Part 5: The Essentials of Text Editing in Linux</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-51-mastering-vim-the-complete-guide">5.1. Mastering Vim: The Complete Guide</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-52-mastering-nano">5.2. Mastering Nano</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-part-6-bash-scripting">Part 6: Bash Scripting</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-61-definition-of-bash-scripting">6.1. Definition of Bash scripting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-62-advantages-of-bash-scripting">6.2. Advantages of Bash Scripting</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-63-overview-of-bash-shell-and-command-line-interface">6.3. Overview of Bash Shell and Command Line Interface</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-64-how-to-create-and-execute-bash-scripts">6.4. How to Create and Execute Bash scripts</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-65-bash-scripting-basics">6.5. Bash Scripting Basics</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-part-7-managing-software-packages-in-linux">Part 7: Managing Software Packages in Linux</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-71-packages-and-package-management">7.1. Packages and Package Management</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-72-installing-a-package-via-command-line">7.2. Installing a Package via Command Line</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-73-installing-a-package-via-an-advanced-graphical-method-synaptic">7.3. Installing a Package via an Advanced Graphical Method – Synaptic</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-74-installing-downloaded-packages-from-a-website">7.4. Installing downloaded packages from a website</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-part-8-advanced-linux-topics">Part 8: Advanced Linux Topics</a></p>
<ul>
<li><p><a class="post-section-overview" href="#heading-81-user-management">8.1. User Management</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-82-connecting-to-remote-servers-via-ssh">8.2 Connecting to Remote Servers via SSH</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-83-advanced-log-parsing-and-analysis">8.3. Advanced Log Parsing and Analysis</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-84-managing-linux-processes-via-command-line">8.4. Managing Linux Processes via Command Line</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-85-standard-input-and-output-streams-in-linux">8.5. Standard Input and Output Streams in Linux</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-86-automation-in-linux-automate-tasks-with-cron-jobs">8.6 Automation in Linux – Automate Tasks with Cron Jobs</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-87-linux-networking-basics">8.7. Linux Networking Basics</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-88-linux-troubleshooting-tools-and-techniques">8.8. Linux Troubleshooting: Tools and Techniques</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-89-general-troubleshooting-strategy-for-servers">8.9. General Troubleshooting Strategy for Servers</a></p>
</li>
<li><p><a class="post-section-overview" href="#heading-810-diagnosing-hardware-problems">8.10 Diagnosing Hardware Problems</a></p>
</li>
</ul>
</li>
<li><p><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></p>
</li>
</ul>
<h2 id="heading-part-1-introduction-to-linux">Part 1: Introduction to Linux</h2>
<h3 id="heading-11-getting-started-with-linux">1.1. Getting Started with Linux</h3>
<h4 id="heading-what-is-linux">What is Linux?</h4>
<p>Linux is an open-source operating system that is based on the Unix operating system. It was created by Linus Torvalds in 1991.</p>
<p>Open source means that the source code of the operating system is available to the public. This allows anyone to modify the original code, customise it, and distribute the new operating system to potential users.</p>
<h4 id="heading-why-should-you-learn-about-linux">Why should you learn about Linux?</h4>
<p>In today's data center landscape, Linux and Microsoft Windows stand out as the primary contenders, with Linux having a major share.</p>
<p>Here are several compelling reasons to learn Linux:</p>
<ul>
<li><p>Given the prevalence of Linux hosting, there is a high chance that your application will be hosted on Linux. So learning Linux as a developer becomes increasingly valuable.</p>
</li>
<li><p>With cloud computing becoming the norm, chances are high that your cloud instances will rely on Linux.</p>
</li>
<li><p>Linux serves as the foundation for many operating systems for the Internet of Things (IoT) and mobile applications.</p>
</li>
<li><p>In IT, there are many opportunities for those skilled in Linux.</p>
</li>
</ul>
<h4 id="heading-what-does-it-mean-that-linux-is-an-open-source-operating-system">What does it mean that Linux is an open-source operating system?</h4>
<p>First, what is open source? Open source software is software whose source code is freely accessible, allowing anyone to utilize, modify, and distribute it.</p>
<p>Whenever source code is created, it is automatically considered copyrighted, and its distribution is governed by the copyright holder through software licenses.</p>
<p>In contrast to open source, proprietary or closed-source software restricts access to its source code. Only the creators can view, modify, or distribute it.</p>
<p>Linux is primarily open source, which means that its source code is freely available. Anyone can view, modify, and distribute it. Developers from anywhere in the world can contribute to its improvement. This lays the foundation of collaboration which is an important aspect of open source software.</p>
<p>This collaborative approach has led to the widespread adoption of Linux across servers, desktops, embedded systems, and mobile devices.</p>
<p>The most interesting aspect of Linux being open source is that anyone can tailor the operating system to their specific needs without being restricted by proprietary limitations.</p>
<p>Chrome OS used by Chromebooks is based on Linux. Android, that powers many smartphones globally, is also based on Linux.</p>
<p><strong>What is a Linux Kernel?</strong></p>
<p>The kernel is the central component of an operating system that manages the computer and its hardware operations. It handles memory operations and CPU time.</p>
<p>The kernel acts as a bridge between applications and the hardware-level data processing using inter-process communication and system calls.</p>
<p>The kernel loads into memory first when an operating system starts and remains there until the system shuts down. It is responsible for tasks like disk management, task management, and memory management.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719844849011/f4bb226e-f319-4cb5-bfc9-c1a80401123e.png" alt="Linux Kernel Layout showing interaction of kernal with applications and OS" class="image--center mx-auto" width="563" height="393" loading="lazy"></p>
<p>If you are curious about what the Linux kernel looks like, <a target="_blank" href="https://github.com/torvalds/linux">here</a> is the GitHub link.</p>
<h4 id="heading-what-is-a-linux-distribution">What is a Linux distribution?</h4>
<p>By this point, you know that you can re-use the Linux kernel code, modify it, and create a new kernel. You can further combine different utilities and software to create a completely new operating system.</p>
<p>A Linux distribution or distro is a version of the Linux operating system that includes the Linux kernel, system utilities, and other software. Being open source, a Linux distribution is a collaborative effort involving multiple independent open-source development communities.</p>
<p><strong>What does it mean that a distribution is derived?</strong> When you say that a distribution is "derived" from another, the newer distro is built upon the base or foundation of the original distro. This derivation can include using the same package management system (more on this later), kernel version, and sometimes the same configuration tools.</p>
<p>Today, there are thousands of Linux distributions to choose from, offering differing goals and criteria for selecting and supporting the software provided by their distribution.</p>
<p>Distributions vary from one to the other, but they generally have several common characteristics:</p>
<ul>
<li><p>A distribution consists of a Linux kernel.</p>
</li>
<li><p>It supports user space programs.</p>
</li>
<li><p>A distribution may be small and single-purpose or include thousands of open-source programs.</p>
</li>
<li><p>Some means of installing and updating the distribution and its components should be provided.</p>
</li>
</ul>
<p>If you view the <a target="_blank" href="https://upload.wikimedia.org/wikipedia/commons/1/1b/Linux_Distribution_Timeline.svg">Linux Distributions Timeline</a>, you'll see two major distros: Slackware and Debian. Several distributions are derived from them. For example, Ubuntu and Kali are derived from Debian.</p>
<p><strong>What are the advantages of derivation?</strong> There are various advantages of derivation. Derived distributions can leverage the stability, security, and large software repositories of the parent distribution.</p>
<p>When building on an existing foundation, developers can drive their focus and effort entirely on the specialized features of the new distribution. Users of derived distributions can benefit from the documentation, community support, and resources already available for the parent distribution.</p>
<p>Some popular Linux distributions are:</p>
<ol>
<li><p><strong>Ubuntu</strong>: One of the most widely used and popular Linux distributions. It is user-friendly and recommended for beginners. <a target="_blank" href="https://ubuntu.com/">Learn more about Ubuntu here</a>.</p>
</li>
<li><p><strong>Linux Mint</strong>: Based on Ubuntu, Linux Mint provides a user-friendly experience with a focus on multimedia support. <a target="_blank" href="https://linuxmint.com/">Learn more about Linux Mint here</a>.</p>
</li>
<li><p><strong>Arch Linux</strong>: Popular among experienced users, Arch is a lightweight and flexible distribution aimed at users who prefer a DIY approach. <a target="_blank" href="https://www.archlinux.org/">Learn more about Arch Linux here</a>.</p>
</li>
<li><p><strong>Manjaro</strong>: Based on Arch Linux, Manjaro provides a user-friendly experience with pre-installed software and easy system management tools. <a target="_blank" href="https://manjaro.org/">Learn more about Manjaro here</a>.</p>
</li>
<li><p><strong>Kali Linux</strong>: Kali Linux provides a comprehensive suite of security tools and is mostly focused on cybersecurity and hacking. <a target="_blank" href="https://www.kali.org/">Learn more about Kali Linux here</a>.</p>
</li>
</ol>
<h4 id="heading-how-to-install-and-access-linux">How to install and access Linux</h4>
<p>The best way to learn is to apply the concepts as you go. In this section, we'll learn how to install Linux on your machine so you can follow along. You'll also learn how to access Linux on a Windows machine.</p>
<p>I recommend that you follow any one of the methods mentioned in this section to get access to Linux so you may follow along.</p>
<h5 id="heading-install-linux-as-the-primary-os">Install Linux as the primary OS</h5>
<p>Installing Linux as the primary OS is the most efficient way to use Linux, as you can use the full power of your machine.</p>
<p>In this section, you will learn how to install Ubuntu, which is one of the most popular Linux distributions. I have left out other distributions for now, as I want to keep things simple. You can always explore other distributions once you are comfortable with Ubuntu.</p>
<ul>
<li><p><strong>Step 1 – Download the Ubuntu iso:</strong> Go to the official <a target="_blank" href="https://ubuntu.com/download/desktop">website</a> and download the iso file. Make sure to select a stable release that is labeled "LTS". LTS stands for Long Term Support which means you can get free security and maintenance updates for a long time (usually 5 years).</p>
</li>
<li><p><strong>Step 2 – Create a bootable pendrive:</strong> There are a number of softwares that can create a bootable pendrive. I recommend using Rufus, as it is quite easy to use. You can download it from <a target="_blank" href="https://rufus.ie/">here</a>.</p>
</li>
<li><p><strong>Step 3 – Boot from the pendrive:</strong> Once your bootable pendrive is ready, insert it and boot from the pendrive. The boot menu depends on your laptop. You can google the boot menu for your laptop model.</p>
</li>
<li><p><strong>Step 4 – Follow the prompts.</strong> Once, the boot process starts, select <code>try or install ubuntu</code>.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719304227675/5b706f94-7368-47ca-a4d6-d55a0d92eff9.png" alt="Screen prompt to either try or install Ubuntu" class="image--center mx-auto" width="611" height="329" loading="lazy"></p>
<p>  The process will take some time. Once the GUI appears, you can select the language, and keyboard layout and continue. Enter your login and name. Remember the credentials as you will need them to log in to your system and access full privileges. Wait for the installation to complete.</p>
</li>
<li><p><strong>Step 5 – Restart:</strong> Click on restart now and remove the pen drive.</p>
</li>
<li><p><strong>Step 6 – Login:</strong> Login with the credentials you entered earlier.</p>
</li>
</ul>
<p>And there you go! Now you can install apps and customize your desktop.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719304547967/d150c6eb-d04e-47e0-8473-d1a837df45c4.png" alt="Ubuntu 22.04.4 LTS Desktop screen" class="image--center mx-auto" width="1920" height="1080" loading="lazy"></p>
<p>For advanced installation, you can explore the following topics:</p>
<ul>
<li><p>Disk partitioning.</p>
</li>
<li><p>Setting swap memory for enabling hibernation.</p>
</li>
</ul>
<p><strong>Accessing the terminal</strong></p>
<p>An important part of this handbook is learning about the terminal where you'll run all the commands and see the magic happen. You can search for the terminal by pressing the "windows" key and typing "terminal". You can pin the Terminal in the dock where other apps are located for easy access.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719305113272/4dd30c5e-da73-4cd4-86bb-7dcd8cd2084c.png" alt="Search results for &quot;terminal&quot;" class="image--center mx-auto" width="437" height="255" loading="lazy"></p>
<blockquote>
<p>💡 The shortcut for opening the terminal is <code>ctrl+alt+t</code></p>
</blockquote>
<p>You can also open the terminal from inside a folder. Right click where you are and click on "Open in Terminal". This will open the terminal in the same path.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719305289021/284a4a53-2d1a-4eaa-925a-1002a32c1dce.png" alt="Opening the terminal with right click menu" class="image--center mx-auto" width="640" height="414" loading="lazy"></p>
<h5 id="heading-how-to-use-linux-on-a-windows-machine">How to use Linux on a Windows machine</h5>
<p>Sometimes you might need to run both Linux and Windows side by side. Luckily, there are some ways you can get the best of both worlds without getting different computers for each operating system.</p>
<p>In this section, you'll explore a few ways to use Linux on a Windows machine. Some of them are browser-based or cloud-based and do not need any OS installation before using them.</p>
<p><strong>Option 1: "Dual-boot" Linux + Windows</strong> With dual boot, you can install Linux alongside Windows on your computer, allowing you to choose which operating system to use at startup.</p>
<p>This requires partitioning your hard drive and installing Linux on a separate partition. With this approach, you can only use one operating system at a time.</p>
<p><strong>Option 2: Use Windows Subsystem for Linux (WSL)</strong> Windows Subsystem for Linux provides a compatibility layer that lets you run Linux binary executables natively on Windows.</p>
<p>Using WSL has some advantages. The setup for WSL is simple and not time-consuming. It is lightweight compared to VMs where you have to allocate resources from the host machine. You don't need to install any ISO or virtual disc image for Linux machines which tend to be heavy files. You can use Windows and Linux side by side.</p>
<p><strong>How to install WSL2</strong></p>
<p>First, enable the Windows Subsystem for Linux option in settings.</p>
<ul>
<li><p>Go to Start. Search for "Turn Windows features on or off."</p>
</li>
<li><p>Check the option "Windows Subsystem for Linux" if it isn't already.</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719306102095/84f23bae-faa5-4ece-a9b6-e40f8789a061.png" alt="Checking the option &quot;Windows Subsystem for Linux&quot; in Windows features" class="image--center mx-auto" width="891" height="550" loading="lazy"></p>
</li>
<li><p>Next, open your command prompt and provide the installation commands.</p>
</li>
<li><p>Open Command Prompt as an administrator:</p>
<p>  <img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1720451480640/6052c9b4-cf07-47e0-ae89-18c3a2d3e385.png" alt="Running command prompt as an admin by right clicking the app and choosing &quot;run as admin£" class="image--center mx-auto" width="1032" height="846" loading="lazy"></p>
</li>
<li><p>Run the command below:</p>
</li>
</ul>
<pre><code class="lang-markdown">wsl --install
</code></pre>
<p>This is the output:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719306131053/b7272031-ddb7-4e04-8d7b-bafc0911da04.png" alt="Downloading progress of Ubuntu" class="image--center mx-auto" width="1099" height="637" loading="lazy"></p>
<p>Note: By default, Ubuntu will be installed.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719306144861/a01f95df-1d95-4b79-bff9-08759be0d3dc.png" alt="Ubuntu installed by default using WSL" class="image--center mx-auto" width="1092" height="626" loading="lazy"></p>
<ul>
<li>Once installation is complete, you'll need to reboot your Windows machine. So, restart your Windows machine.</li>
</ul>
<p>After restarting, you might see a window like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719306157704/15620fbe-59d1-40da-9cd6-119a1fab0802.png" alt="Window that shows after a restart" class="image--center mx-auto" width="1111" height="647" loading="lazy"></p>
<p>Once installation of Ubuntu is complete, you'll be prompted to enter your username and password.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719306167380/5e3058cd-b7a1-45b1-a16d-c23b5a451504.png" alt="User prompted to enter a username and password" class="image--center mx-auto" width="908" height="611" loading="lazy"></p>
<p>And, that's it! You are ready to use Ubuntu.</p>
<p>Launch Ubuntu by searching from the start menu.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719306185110/77c17856-08ac-4ec7-9380-5b06f93be095.png" alt="Launching Ubuntu from the start menu" class="image--center mx-auto" width="966" height="846" loading="lazy"></p>
<p>And here we have your Ubuntu instance launched.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719306196320/13be3a71-5b40-440c-a6bf-d742e5b5934b.png" alt="Successful installation of Ubuntu using WSL" class="image--center mx-auto" width="1103" height="639" loading="lazy"></p>
<p><strong>Option 3: Use a Virtual Machine (VM)</strong></p>
<p>A virtual machine (VM) is a software emulation of a physical computer system. It allows you to run multiple operating systems and applications on a single physical machine simultaneously.</p>
<p>You can use virtualization software such as Oracle VirtualBox or VMware to create a virtual machine running Linux within your Windows environment. This allows you to run Linux as a guest operating system alongside Windows.</p>
<p>VM software provides options to allocate and manage hardware resources for each VM, including CPU cores, memory, disk space, and network bandwidth. You can adjust these allocations based on the requirements of the guest operating systems and applications.</p>
<p>Here are some of the common options available for virtualization:</p>
<ul>
<li><p><a target="_blank" href="https://www.virtualbox.org/">Oracle virtual box</a></p>
</li>
<li><p><a target="_blank" href="https://multipass.run/">Multipass</a></p>
</li>
<li><p><a target="_blank" href="https://www.vmware.com/content/vmware/vmware-published-sites/us/products/workstation-player.html.html">VMware workstation player</a></p>
</li>
</ul>
<p><strong>Option 4: Use a Browser-based Solution</strong></p>
<p>Browser-based solutions are particularly useful for quick testing, learning, or accessing Linux environments from devices that don't have Linux installed.</p>
<p>You can either use online code editors or web-based terminals to access Linux. Note that you usually don't have full administration privileges in these cases.</p>
<h4 id="heading-online-code-editors"><strong>Online code editors</strong></h4>
<p>Online code editors offer editors with built-in Linux terminals. While their primary purpose is coding, you can also utilize the Linux terminal to execute commands and perform tasks.</p>
<p><a target="_blank" href="https://replit.com/">Replit</a> is an example of an online code editor, where you can write your code and access the Linux shell at the same time.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719306257260/d85d5541-b78f-4c8b-99a8-dbd8c097f661.gif" alt="Running scripts and a bash shell in Replit" class="image--center mx-auto" width="1520" height="721" loading="lazy"></p>
<h4 id="heading-web-based-linux-terminals"><strong>Web-based Linux terminals:</strong></h4>
<p>Online Linux terminals allow you to access a Linux command-line interface directly from your browser. These terminals provide a web-based interface to a Linux shell, enabling you to execute commands and work with Linux utilities.</p>
<p>One such example is <a target="_blank" href="https://jslinux.org/">JSLinux</a>. The screenshot below shows a ready-to-use Linux environment:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719306276915/ddaabfc3-9a20-43b2-bedc-0af6875d2008.png" alt="Using JSLinux to access Linux terminal" class="image--center mx-auto" width="826" height="765" loading="lazy"></p>
<p><strong>Option 5: Use a Cloud-based Solution</strong></p>
<p>Instead of running Linux directly on your Windows machine, you can consider using cloud-based Linux environments or virtual private servers (VPS) to access and work with Linux remotely.</p>
<p>Services like Amazon EC2, Microsoft Azure, or DigitalOcean provide Linux instances that you can connect to from your Windows computer. Note that some of these services offer free tiers, but they are not usually free in the long run.</p>
<h2 id="heading-part-2-introduction-to-bash-shell-and-system-commands">Part 2: Introduction to Bash Shell and System Commands</h2>
<h3 id="heading-21-getting-started-with-the-bash-shell">2.1. Getting Started with the Bash shell</h3>
<h4 id="heading-introduction-to-the-bash-shell">Introduction to the bash shell</h4>
<p>The Linux command line is provided by a program called the shell. Over the years, the shell program has evolved to cater to various options.</p>
<p>Different users can be configured to use different shells. But, most users prefer to stick with the current default shell. The default shell for many Linux distros is the GNU Bourne-Again Shell (<code>bash</code>). Bash is succeeded by the Bourne shell (<code>sh</code>).</p>
<p>To find out your current shell, open your terminal and enter the following command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-variable">$SHELL</span>
</code></pre>
<p>Command breakdown:</p>
<ul>
<li><p>The <code>echo</code> command is used to print on the terminal.</p>
</li>
<li><p>The <code>$SHELL</code> is a special variable that holds the name of the current shell.</p>
</li>
</ul>
<p>In my setup, the output is <code>/bin/bash</code>. This means that I am using the bash shell.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># output</span>
<span class="hljs-built_in">echo</span> <span class="hljs-variable">$SHELL</span>
/bin/bash
</code></pre>
<p>Bash is very powerful as it can simplify certain operations that are hard to accomplish efficiently with a GUI (or Graphical User Interface). Remember that most servers do not have a GUI, and it is best to learn to use the powers of a command line interface (CLI).</p>
<p><strong>Terminal vs Shell</strong></p>
<p>The terms "terminal" and "shell" are often used interchangeably, but they refer to different parts of the command-line interface.</p>
<p>The terminal is the interface you use to interact with the shell. The shell is the command interpreter that processes and executes your commands. You'll learn more about shells in Part 6 of the handbook.</p>
<h4 id="heading-what-is-a-prompt">What is a prompt?</h4>
<p>When a shell is used interactively, it displays a <code>$</code> when it is waiting for a command from the user. This is called the shell prompt.</p>
<p><code>[username@host ~]$</code></p>
<p>If the shell is running as <code>root</code> (you'll learn more about the root user later on), the prompt is changed to <code>#</code>.</p>
<p><code>[root@host ~]#</code></p>
<h3 id="heading-22-command-structure">2.2. Command Structure</h3>
<p>A command is a program that performs a specific operation. Once you have access to the shell, you can enter any command after the <code>$</code> sign and see the output on the terminal.</p>
<p>Generally, Linux commands follow this syntax:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">command</span> [options] [arguments]
</code></pre>
<p>Here is the breakdown of the above syntax:</p>
<ul>
<li><p><code>command</code>: This is the name of the command you want to execute. <code>ls</code> (list), <code>cp</code> (copy), and <code>rm</code> (remove) are common Linux commands.</p>
</li>
<li><p><code>[options]</code>: Options, or flags, often preceded by a hyphen (-) or double hyphen (--), modify the behavior of the command. They can change how the command operates. For example, <code>ls -a</code> uses the <code>-a</code> option to display hidden files in the current directory.</p>
</li>
<li><p><code>[arguments]</code>: Arguments are the inputs for the commands that require one. These could be filenames, user names, or other data that the command will act upon. For example, in the command <code>cat access.log</code>, <code>cat</code> is the command and <code>access.log</code> is the input. As a result, the <code>cat</code> command displays the contents of the <code>access.log</code> file.</p>
</li>
</ul>
<p>Options and arguments are not required for all commands. Some commands can be run without any options or arguments, while others might require one or both to function correctly. You can always refer to the command's manual to check the options and arguments it supports.</p>
<p>💡<strong>Tip:</strong> You can view a command's manual using the <code>man</code> command.</p>
<p>You can access the manual page for <code>ls</code> with <code>man ls</code>, and it'll look like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719312523336/5b1232a6-8c0b-4a97-86f0-9f15f2e14ed7.png" alt="5b1232a6-8c0b-4a97-86f0-9f15f2e14ed7" class="image--center mx-auto" width="1890" height="969" loading="lazy"></p>
<p>Manual pages are a great and quick way to access the documentation. I highly recommend going through man pages for the commands that you use the most.</p>
<h3 id="heading-23-bash-commands-and-keyboard-shortcuts">2.3. Bash Commands and Keyboard Shortcuts</h3>
<p>When you are in the terminal, you can speed up your tasks by using shortcuts.</p>
<p>Here are some of the most common terminal shortcuts:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Operation</td><td>Shortcut</td></tr>
</thead>
<tbody>
<tr>
<td>Look for the previous command</td><td>Up Arrow</td></tr>
<tr>
<td>Jump to the beginning of the previous word</td><td>Ctrl+LeftArrow</td></tr>
<tr>
<td>Clear characters from the cursor to the end of the command line</td><td>Ctrl+K</td></tr>
<tr>
<td>Complete commands, file names, and options</td><td>Pressing Tab</td></tr>
<tr>
<td>Jumps to the beginning of the command line</td><td>Ctrl+A</td></tr>
<tr>
<td>Displays the list of previous commands</td><td>history</td></tr>
</tbody>
</table>
</div><h3 id="heading-24-identifying-yourself-the-whoami-command">2.4. Identifying Yourself: The <code>whoami</code> Command</h3>
<p>You can get the username you are logged in with by using the <code>whoami</code> command. This command is useful when you are switching between different users and want to confirm the current user.</p>
<p>Just after the <code>$</code> sign, type <code>whoami</code> and press enter.</p>
<pre><code class="lang-bash">whoami
</code></pre>
<p>This is the output I got.</p>
<pre><code class="lang-bash">zaira@zaira-ThinkPad:~$ whoami
zaira
</code></pre>
<h2 id="heading-part-3-understanding-your-linux-system">Part 3: Understanding Your Linux System</h2>
<h3 id="heading-31-discovering-your-os-and-specs">3.1. Discovering Your OS and Specs</h3>
<h4 id="heading-print-system-information-using-the-uname-command">Print system information using the <code>uname</code> Command</h4>
<p>You can get detailed system information from the <code>uname</code> command.</p>
<p>When you provide the <code>-a</code> option, it prints all the system information.</p>
<pre><code class="lang-bash">uname -a
<span class="hljs-comment"># output</span>
Linux zaira 6.5.0-21-generic <span class="hljs-comment">#21~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Feb  9 13:32:52 UTC 2 x86_64 x86_64 x86_64 GNU/Linux</span>
</code></pre>
<p>In the output above,</p>
<ul>
<li><p><code>Linux</code>: Indicates the operating system.</p>
</li>
<li><p><code>zaira</code>: Represents the hostname of the machine.</p>
</li>
<li><p><code>6.5.0-21-generic #21~22.04.1-Ubuntu SMP PREEMPT_DYNAMIC Fri Feb 9 13:32:52 UTC 2</code>: Provides information about the kernel version, build date, and some additional details.</p>
</li>
<li><p><code>x86_64 x86_64 x86_64</code>: Indicates the architecture of the system.</p>
</li>
<li><p><code>GNU/Linux</code>: Represents the operating system type.</p>
</li>
</ul>
<h4 id="heading-find-details-of-the-cpu-architecture-using-the-lscpu-command">Find details of the CPU architecture using the <code>lscpu</code> Command</h4>
<p>The <code>lscpu</code> command in Linux is used to display information about the CPU architecture. When you run <code>lscpu</code> in the terminal, it provides details such as:</p>
<ul>
<li><p>The architecture of the CPU (for example, x86_64)</p>
</li>
<li><p>CPU op-mode(s) (for example, 32-bit, 64-bit)</p>
</li>
<li><p>Byte Order (for example, Little Endian)</p>
</li>
<li><p>CPU(s) (number of CPUs), and so on</p>
<p>  Let's try it out:</p>
</li>
</ul>
<pre><code class="lang-bash">lscpu
<span class="hljs-comment"># output</span>
Architecture:            x86_64
  CPU op-mode(s):        32-bit, 64-bit
  Address sizes:         48 bits physical, 48 bits virtual
  Byte Order:            Little Endian
CPU(s):                  12
  On-line CPU(s) list:   0-11
Vendor ID:               AuthenticAMD
  Model name:            AMD Ryzen 5 5500U with Radeon Graphics
    Thread(s) per core:  2
    Core(s) per socket:  6
    Socket(s):           1
    Stepping:            1
    CPU max MHz:         4056.0000
    CPU min MHz:         400.0000
</code></pre>
<p>That was a whole lot of information, but useful too! Remember you can always skim the relevant information using specific flags. See the command manual with <code>man lscpu</code>.</p>
<h2 id="heading-part-4-managing-files-from-the-command-line">Part 4: Managing Files From the Command line</h2>
<h3 id="heading-41-the-linux-file-system-hierarchy">4.1. The Linux File-system Hierarchy</h3>
<p>All files in Linux are stored in a file-system. It follows an inverted-tree-like structure because the root is at the topmost part.</p>
<p>The <code>/</code> is the root directory and the starting point of the file system. The root directory contains all other directories and files on the system. The <code>/</code> character also serves as a directory separator between path names. For example, <code>/home/alice</code> forms a complete path.</p>
<p>The image below shows the complete file system hierarchy. Each directory servers a specific purpose.</p>
<p>Note that this is not an exhaustive list and different distributions may have different configurations.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719322457140/02fdbf2c-f4fa-438b-af2f-c23f59f9ddf4.png" alt="Linux file system hierarchy" class="image--center mx-auto" width="1455" height="474" loading="lazy"></p>
<p>Here is a table that shows the purpose of each directory:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Location</td><td>Purpose</td></tr>
</thead>
<tbody>
<tr>
<td>/bin</td><td>Essential command binaries</td></tr>
<tr>
<td>/boot</td><td>Static files of the boot loader, needed in order to start the boot process.</td></tr>
<tr>
<td>/etc</td><td>Host-specific system configuration</td></tr>
<tr>
<td>/home</td><td>User home directories</td></tr>
<tr>
<td>/root</td><td>Home directory for the administrative root user</td></tr>
<tr>
<td>/lib</td><td>Essential shared libraries and kernel modules</td></tr>
<tr>
<td>/mnt</td><td>Mount point for mounting a filesystem temporarily</td></tr>
<tr>
<td>/opt</td><td>Add-on application software packages</td></tr>
<tr>
<td>/usr</td><td>Installed software and shared libraries</td></tr>
<tr>
<td>/var</td><td>Variable data that is also persistent between boots</td></tr>
<tr>
<td>/tmp</td><td>Temporary files that are accessible to all users</td></tr>
</tbody>
</table>
</div><p>💡 <strong>Tip:</strong> You can learn more about the file system using the <code>man hier</code> command.</p>
<p>You can check your file system using the <code>tree -d -L 1</code> command. You can modify the <code>-L</code> flag to change the depth of the tree.</p>
<pre><code class="lang-bash">tree -d -L 1
<span class="hljs-comment"># output</span>
.
├── bin -&gt; usr/bin
├── boot
├── cdrom
├── data
├── dev
├── etc
├── home
├── lib -&gt; usr/lib
├── lib32 -&gt; usr/lib32
├── lib64 -&gt; usr/lib64
├── libx32 -&gt; usr/libx32
├── lost+found
├── media
├── mnt
├── opt
├── proc
├── root
├── run
├── sbin -&gt; usr/sbin
├── snap
├── srv
├── sys
├── tmp
├── usr
└── var

25 directories
</code></pre>
<p>This list is not exhaustive and different distributions and systems may be configured differently.</p>
<h3 id="heading-42-navigating-the-linux-file-system">4.2. Navigating the Linux File-system</h3>
<h4 id="heading-absolute-path-vs-relative-path">Absolute path vs relative path</h4>
<p>The absolute path is the full path from the root directory to the file or directory. It always starts with a <code>/</code>. For example, <code>/home/john/documents</code>.</p>
<p>The relative path, on the other hand, is the path from the current directory to the destination file or directory. It does not start with a <code>/</code>. For example, <code>documents/work/project</code>.</p>
<h4 id="heading-locating-your-current-directory-using-the-pwd-command">Locating your current directory using the <code>pwd</code> command</h4>
<p>It is easy to lose your way in the Linux file system, especially if you are new to the command line. You can locate your current directory using the <code>pwd</code> command.</p>
<p>Here is an example:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">pwd</span>
<span class="hljs-comment"># output</span>
/home/zaira/scripts/python/free-mem.py
</code></pre>
<h4 id="heading-changing-directories-using-the-cd-command">Changing directories using the <code>cd</code> command</h4>
<p>The command to change directories is <code>cd</code> and it stands for "change directory". You can use the <code>cd</code> command to navigate to a different directory.</p>
<p>You can use a relative path or an absolute path.</p>
<p>For example, if you want to navigate the below file structure (following the red lines):</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719389950079/640cce46-6c52-4f38-9787-581747fb9798.png" alt="Example file structure" class="image--center mx-auto" width="327" height="253" loading="lazy"></p>
<p>and you are standing at "home", the command would be like this:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> home/bob/documents/work/project
</code></pre>
<p>Some other commonly used <code>cd</code> shortcuts are:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Command</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>cd ..</code></td><td>Go back one directory</td></tr>
<tr>
<td><code>cd ../..</code></td><td>Go back two directories</td></tr>
<tr>
<td><code>cd</code> or <code>cd ~</code></td><td>Go to the home directory</td></tr>
<tr>
<td><code>cd -</code></td><td>Go to the previous path</td></tr>
</tbody>
</table>
</div><h3 id="heading-43-managing-files-and-directories">4.3. Managing Files and Directories</h3>
<p>When working with files and directories, you might want to copy, move, remove, and create new files and directories. Here are some commands that can help you with that.</p>
<p>💡<strong>Tip:</strong> You can differentiate between a file and folder by looking at the first letter in the output of <code>ls -l</code>. A<code>'-'</code> represents a file and a <code>'d'</code> represents a folder.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719390306244/4f1688cd-ded5-43fe-b13a-9ca44ac7c4ad.png" alt="&quot;d&quot; represents a folder" class="image--center mx-auto" width="766" height="226" loading="lazy"></p>
<h4 id="heading-creating-new-directories-using-the-mkdir-command">Creating new directories using the <code>mkdir</code> command</h4>
<p>You can create an empty directory using the <code>mkdir</code> command.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># creates an empty directory named "foo" in the current folder</span>
mkdir foo
</code></pre>
<p>You can also create directories recursively using the <code>-p</code> option.</p>
<pre><code class="lang-bash">mkdir -p tools/index/helper-scripts
<span class="hljs-comment"># output of tree</span>
.
└── tools
    └── index
        └── helper-scripts

3 directories, 0 files
</code></pre>
<h4 id="heading-creating-new-files-using-the-touch-command">Creating new files using the <code>touch</code> command</h4>
<p>The <code>touch</code> command creates an empty file. You can use it like this:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># creates empty file "file.txt" in the current folder</span>
touch file.txt
</code></pre>
<p>The file names can be chained together if you want to create multiple files in a single command.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># creates empty files "file1.txt", "file2.txt", and "file3.txt" in the current folder</span>

touch file1.txt file2.txt file3.txt
</code></pre>
<h4 id="heading-removing-files-and-directories-using-the-rm-and-rmdir-command">Removing files and directories using the <code>rm</code> and <code>rmdir</code> command</h4>
<p>You can use the <code>rm</code> command to remove both files and non-empty directories.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Command</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>rm file.txt</code></td><td>Removes the file <code>file.txt</code></td></tr>
<tr>
<td><code>rm -r directory</code></td><td>Removes the directory <code>directory</code> and its contents</td></tr>
<tr>
<td><code>rm -f file.txt</code></td><td>Removes the file <code>file.txt</code> without prompting for confirmation</td></tr>
<tr>
<td><code>rmdir</code> directory</td><td>Removes an empty directory</td></tr>
</tbody>
</table>
</div><p>🛑 Note that you should use the <code>-f</code> flag with caution as you won't be asked before deleting a file. Also, be careful when running <code>rm</code> commands in the <code>root</code> folder as it might result in deleting important system files.</p>
<h4 id="heading-copying-files-using-the-cp-command">Copying files using the <code>cp</code> command</h4>
<p>To copy files in Linux, use the <code>cp</code> command.</p>
<ul>
<li><strong>Syntax to copy files:</strong><code>cp source_file destination_of_file</code></li>
</ul>
<p>This command copies a file named <code>file1.txt</code> to a new file location <code>/home/adam/logs</code>.</p>
<pre><code class="lang-bash">cp file1.txt /home/adam/logs
</code></pre>
<p>The <code>cp</code> command also creates a copy of one file with the provided name.</p>
<p>This command copies a file named <code>file1.txt</code> to another file named <code>file2.txt</code> in the same folder.</p>
<pre><code class="lang-bash">cp file1.txt file2.txt
</code></pre>
<h4 id="heading-moving-and-renaming-files-and-folders-using-the-mv-command">Moving and renaming files and folders using the <code>mv</code> command</h4>
<p>The <code>mv</code> command is used to move files and folders from one directory to the other.</p>
<p><strong>Syntax to move files:</strong><code>mv source_file destination_directory</code></p>
<p><strong>Example:</strong> Move a file named <code>file1.txt</code> to a directory named <code>backup</code>:</p>
<pre><code class="lang-bash">mv file1.txt backup/
</code></pre>
<p>To move a directory and its contents:</p>
<pre><code class="lang-bash">mv dir1/ backup/
</code></pre>
<p>Renaming files and folders in Linux is also done with the <code>mv</code> command.</p>
<p><strong>Syntax to rename files:</strong><code>mv old_name new_name</code></p>
<p><strong>Example:</strong> Rename a file from <code>file1.txt</code> to <code>file2.txt</code>:</p>
<pre><code class="lang-bash">mv file1.txt file2.txt
</code></pre>
<p>Rename a directory from <code>dir1</code> to <code>dir2</code>:</p>
<pre><code class="lang-bash">mv dir1 dir2
</code></pre>
<h3 id="heading-44-locating-files-and-folders-using-the-find-command">4.4. Locating Files and Folders Using the <code>find</code> Command</h3>
<p>The <code>find</code> command lets you efficiently search for files, folders, and character and block devices.</p>
<p>Below is the basic syntax of the <code>find</code> command:</p>
<pre><code class="lang-bash">find /path/ -<span class="hljs-built_in">type</span> f -name file-to-search
</code></pre>
<p>Where,</p>
<ul>
<li><p><code>/path</code> is the path where the file is expected to be found. This is the starting point for searching files. The path can also be<code>/</code>or <code>.</code> which represents the root and current directory, respectively.</p>
</li>
<li><p><code>-type</code> represents the file descriptors. They can be any of the below:<br>  <code>f</code> – <strong>Regular file</strong> such as text files, images, and hidden files.<br>  <code>d</code> – <strong>Directory</strong>. These are the folders under consideration.<br>  <code>l</code> – <strong>Symbolic link</strong>. Symbolic links point to files and are similar to shortcuts.<br>  <code>c</code> – <strong>Character devices</strong>. Files that are used to access character devices are called character device files. Drivers communicate with character devices by sending and receiving single characters (bytes, octets). Examples include keyboards, sound cards, and the mouse.<br>  <code>b</code> – <strong>Block devices</strong>. Files that are used to access block devices are called block device files. Drivers communicate with block devices by sending and receiving entire blocks of data. Examples include USB and CD-ROM</p>
</li>
<li><p><code>-name</code> is the name of the file type that you want to search.</p>
</li>
</ul>
<h4 id="heading-how-to-search-files-by-name-or-extension">How to search files by name or extension</h4>
<p>Suppose we need to find files that contain "style" in their name. We'll use this command:</p>
<pre><code class="lang-bash">find . -<span class="hljs-built_in">type</span> f -name <span class="hljs-string">"style*"</span>
<span class="hljs-comment">#output</span>
./style.css
./styles.css
</code></pre>
<p>Now let's say we want to find files with a particular extension like <code>.html</code>. We'll modify the command like this:</p>
<pre><code class="lang-bash">find . -<span class="hljs-built_in">type</span> f -name <span class="hljs-string">"*.html"</span>
<span class="hljs-comment"># output</span>
./services.html
./blob.html
./index.html
</code></pre>
<h4 id="heading-how-to-search-hidden-files">How to search hidden files</h4>
<p>A dot at the beginning of the filename represents hidden files. They are normally hidden but can be viewed with <code>ls -a</code> in the current directory.</p>
<p>We can modify the <code>find</code> command as shown below to search for hidden files:</p>
<pre><code class="lang-bash">find . -<span class="hljs-built_in">type</span> f -name <span class="hljs-string">".*"</span>
</code></pre>
<p><strong>List and find hidden files</strong></p>
<pre><code class="lang-bash">ls -la
<span class="hljs-comment"># folder contents</span>
total 5
drwxrwxr-x  2 zaira zaira 4096 Mar 26 14:17 .
drwxr-x--- 61 zaira zaira 4096 Mar 26 14:12 ..
-rw-rw-r--  1 zaira zaira    0 Mar 26 14:17 .bash_history
-rw-rw-r--  1 zaira zaira    0 Mar 26 14:17 .bash_logout
-rw-rw-r--  1 zaira zaira    0 Mar 26 14:17 .bashrc

find . -<span class="hljs-built_in">type</span> f -name <span class="hljs-string">".*"</span>
<span class="hljs-comment"># find output</span>
./.bash_logout
./.bashrc
./.bash_history
</code></pre>
<p>Above you can see a list of hidden files in my home directory.</p>
<h4 id="heading-how-to-search-log-files-and-configuration-files">How to search log files and configuration files</h4>
<p>Log files usually have the extension <code>.log</code>, and we can find them like this:</p>
<pre><code class="lang-bash"> find . -<span class="hljs-built_in">type</span> f -name <span class="hljs-string">"*.log"</span>
</code></pre>
<p>Similarly, we can search for configuration files like this:</p>
<pre><code class="lang-bash"> find . -<span class="hljs-built_in">type</span> f -name <span class="hljs-string">"*.conf"</span>
</code></pre>
<h4 id="heading-how-to-search-other-files-by-type">How to search other files by type</h4>
<p>We can search for character block files by providing <code>c</code> to <code>-type</code>:</p>
<pre><code class="lang-bash">find / -<span class="hljs-built_in">type</span> c
</code></pre>
<p>Similarly, we can find device block files by using <code>b</code>:</p>
<pre><code class="lang-bash">find / -<span class="hljs-built_in">type</span> b
</code></pre>
<h4 id="heading-how-to-search-directories">How to search directories</h4>
<p>In the example below, we are finding the folders using the <code>-type d</code> flag.</p>
<pre><code class="lang-bash">ls -l
<span class="hljs-comment"># list folder contents</span>
drwxrwxr-x 2 zaira zaira 4096 Mar 26 14:22 hosts
-rw-rw-r-- 1 zaira zaira    0 Mar 26 14:23 hosts.txt
drwxrwxr-x 2 zaira zaira 4096 Mar 26 14:22 images
drwxrwxr-x 2 zaira zaira 4096 Mar 26 14:23 style
drwxrwxr-x 2 zaira zaira 4096 Mar 26 14:22 webp 

find . -<span class="hljs-built_in">type</span> d 
<span class="hljs-comment"># find directory output</span>
.
./webp
./images
./style
./hosts
</code></pre>
<h4 id="heading-how-to-search-files-by-size">How to search files by size</h4>
<p>An incredibly helpful use of the <code>find</code> command is to list files based on a particular size.</p>
<pre><code class="lang-bash">find / -size +250M
</code></pre>
<p>Here, we are listing files whose size exceeds <code>250MB</code>.</p>
<p>Other units include:</p>
<ul>
<li><p><code>G</code>: GigaBytes.</p>
</li>
<li><p><code>M</code>: MegaBytes.</p>
</li>
<li><p><code>K</code>: KiloBytes</p>
</li>
<li><p><code>c</code> : bytes.</p>
</li>
</ul>
<p>Just replace with the relevant unit.</p>
<pre><code class="lang-bash">find &lt;directory&gt; -<span class="hljs-built_in">type</span> f -size +N&lt;Unit Type&gt;
</code></pre>
<h4 id="heading-how-to-search-files-by-modification-time">How to search files by modification time</h4>
<p>By using the <code>-mtime</code> flag, you can filter files and folders based on the modification time.</p>
<pre><code class="lang-bash">find /path -name <span class="hljs-string">"*.txt"</span> -mtime -10
</code></pre>
<p>For example,</p>
<ul>
<li><p><strong>-mtime +10</strong> means you are looking for a file modified 10 days ago.</p>
</li>
<li><p><strong>-mtime -10</strong> means less than 10 days.</p>
</li>
<li><p><strong>-mtime 10</strong> If you skip + or – it means exactly 10 days.</p>
</li>
</ul>
<h3 id="heading-45-basic-commands-for-viewing-files">4.5. Basic Commands for Viewing Files</h3>
<h4 id="heading-concatenate-and-display-files-using-the-cat-command">Concatenate and display files using the <code>cat</code> command</h4>
<p>The <code>cat</code> command in Linux is used to display the contents of a file. It can also be used to concatenate files and create new files.</p>
<p>Here is the basic syntax of the <code>cat</code> command:</p>
<pre><code class="lang-bash">cat [options] [file]
</code></pre>
<p>The simplest way to use <code>cat</code> is without any options or arguments. This will display the contents of the file on the terminal.</p>
<p>For example, if you want to view the contents of a file named <code>file.txt</code>, you can use the following command:</p>
<pre><code class="lang-bash">cat file.txt
</code></pre>
<p>This will display all the contents of the file on the terminal at once.</p>
<h4 id="heading-viewing-text-files-interactively-using-less-and-more">Viewing text files interactively using <code>less</code> and <code>more</code></h4>
<p>While <code>cat</code> displays the entire file at once, <code>less</code> and <code>more</code> allow you to view the contents of a file interactively. This is useful when you want to scroll through a large file or search for specific content.</p>
<p>The syntax of the <code>less</code> command is:</p>
<pre><code class="lang-bash">less [options] [file]
</code></pre>
<p>The <code>more</code> command is similar to <code>less</code> but has fewer features. It is used to display the contents of a file one screen at a time.</p>
<p>The syntax of the <code>more</code> command is:</p>
<pre><code class="lang-bash">more [options] [file]
</code></pre>
<p>For both commands, you can use the <code>spacebar</code> to scroll one page down, the <code>Enter</code> key to scroll one line down, and the <code>q</code> key to exit the viewer.</p>
<p>To move backward you can use the <code>b</code> key, and to move forward you can use the <code>f</code> key.</p>
<h4 id="heading-displaying-the-last-part-of-files-using-tail">Displaying the last part of files using <code>tail</code></h4>
<p>Sometimes you might need to view just the last few lines of a file instead of the entire file. The <code>tail</code> command in Linux is used to display the last part of a file.</p>
<p>For example, <code>tail file.txt</code> will display the last 10 lines of the file <code>file.txt</code> by default.</p>
<p>If you want to display a different number of lines, you can use the <code>-n</code> option followed by the number of lines you want to display.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Display the last 50 lines of the file file.txt</span>
tail -n 50 file.txt
</code></pre>
<p>💡<strong>Tip:</strong> Another usage of the <code>tail</code> is its follow-along (<code>-f</code>) option. This option enables you to view the contents of a file as they are being written. This is a useful utility for viewing and monitoring log files in real-time.</p>
<h4 id="heading-displaying-the-beginning-of-files-using-head">Displaying the beginning of files using <code>head</code></h4>
<p>Just like <code>tail</code> displays the last part of a file, you can use the <code>head</code> command in Linux to display the beginning of a file.</p>
<p>For example, <code>head file.txt</code> will display the first 10 lines of the file <code>file.txt</code> by default.</p>
<p>To change the number of lines displayed, you can use the <code>-n</code> option followed by the number of lines you want to display.</p>
<h4 id="heading-counting-words-lines-and-characters-using-wc">Counting words, lines, and characters using <code>wc</code></h4>
<p>You can count words, lines and characters in a file using the <code>wc</code> command.</p>
<p>For example, running <code>wc syslog.log</code> gave me the following output:</p>
<pre><code class="lang-bash">1669 9623 64367 syslog.log
</code></pre>
<p>In the output above,</p>
<ul>
<li><p><code>1669</code> represents the number of lines in the file <code>syslog.log</code>.</p>
</li>
<li><p><code>9623</code> represents the number of words in the file <code>syslog.log</code>.</p>
</li>
<li><p><code>64367</code> represents the number of characters in the file <code>syslog.log</code>.</p>
</li>
</ul>
<p>So, the command <code>wc syslog.log</code> counted <code>1669</code> lines, <code>9623</code> words, and <code>64367</code> characters in the file <code>syslog.log</code>.</p>
<h4 id="heading-comparing-files-line-by-line-using-diff">Comparing files line by line using <code>diff</code></h4>
<p>Comparing and finding differences between two files is a common task in Linux. You can compare two files right within the command line using the <code>diff</code> command.</p>
<p>The basic syntax of the <code>diff</code> command is:</p>
<pre><code class="lang-bash">diff [options] file1 file2
</code></pre>
<p>Here are two files, <code>hello.py</code> and <code>also-hello.py</code>, that we will compare using the <code>diff</code> command:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># contents of hello.py</span>

def greet(name):
    <span class="hljs-built_in">return</span> f<span class="hljs-string">"Hello, {name}!"</span>

user = input(<span class="hljs-string">"Enter your name: "</span>)
<span class="hljs-built_in">print</span>(greet(user))
</code></pre>
<pre><code class="lang-bash"><span class="hljs-comment"># contents of also-hello.py</span>

more also-hello.py
def greet(name):
    <span class="hljs-built_in">return</span> fHello, {name}!

user = input(Enter your name: )
<span class="hljs-built_in">print</span>(greet(user))
<span class="hljs-built_in">print</span>(<span class="hljs-string">"Nice to meet you"</span>)
</code></pre>
<ol>
<li>Check whether the files are the same or not</li>
</ol>
<pre><code class="lang-bash">diff -q hello.py also-hello.py
<span class="hljs-comment"># Output</span>
Files hello.py and also-hello.py differ
</code></pre>
<ol start="2">
<li>See how the files differ. For that, you can use the <code>-u</code> flag to see a unified output:</li>
</ol>
<pre><code class="lang-bash">diff -u hello.py also-hello.py
--- hello.py    2024-05-24 18:31:29.891690478 +0500
+++ also-hello.py    2024-05-24 18:32:17.207921795 +0500
@@ -3,4 +3,5 @@

 user = input(Enter your name: )
 <span class="hljs-built_in">print</span>(greet(user))
+<span class="hljs-built_in">print</span>(<span class="hljs-string">"Nice to meet you"</span>)
</code></pre>
<p>In the above output:</p>
<ul>
<li><p><code>--- hello.py 2024-05-24 18:31:29.891690478 +0500</code> indicates the file being compared and its timestamp.</p>
</li>
<li><p><code>+++ also-hello.py 2024-05-24 18:32:17.207921795 +0500</code> indicates the other file being compared and its timestamp.</p>
</li>
<li><p><code>@@ -3,4 +3,5 @@</code> shows the line numbers where the changes occur. In this case, it indicates that lines 3 to 4 in the original file have changed to lines 3 to 5 in the modified file.</p>
</li>
<li><p><code>user = input(Enter your name: )</code> is a line from the original file.</p>
</li>
<li><p><code>print(greet(user))</code> is another line from the original file.</p>
</li>
<li><p><code>+print("Nice to meet you")</code> is the additional line in the modified file.</p>
</li>
</ul>
<ol start="3">
<li>To see the diff in a side-by-side format, you can use the <code>-y</code> flag:</li>
</ol>
<pre><code class="lang-bash">diff -y hello.py also-hello.py
<span class="hljs-comment"># Output</span>
def greet(name):                        def greet(name):
    <span class="hljs-built_in">return</span> fHello, {name}!                        <span class="hljs-built_in">return</span> fHello, {name}!

user = input(Enter your name: )                    user = input(Enter your name: )
<span class="hljs-built_in">print</span>(greet(user))                        <span class="hljs-built_in">print</span>(greet(user))
                                        &gt;    <span class="hljs-built_in">print</span>(<span class="hljs-string">"Nice to meet you"</span>)
</code></pre>
<p>In the output:</p>
<ul>
<li><p>The lines that are the same in both files are displayed side by side.</p>
</li>
<li><p>Lines that are different are shown with a <code>&gt;</code> symbol indicating the line is only present in one of the files.</p>
</li>
</ul>
<h2 id="heading-part-5-the-essentials-of-text-editing-in-linux">Part 5: The Essentials of Text Editing in Linux</h2>
<p>Text editing skills using the command line are one of the most crucial skills in Linux. In this section, you will learn how to use two popular text editors in Linux: Vim and Nano.</p>
<p>I suggest that you master any one text editor of your choice and stick to it. It will save you time and make you more productive. Vim and nano are safe choices as they are present on most Linux distributions.</p>
<h3 id="heading-51-mastering-vim-the-complete-guide">5.1. Mastering Vim: The Complete Guide</h3>
<h4 id="heading-introduction-to-vim">Introduction to Vim</h4>
<p>Vim is a popular text editing tool for the command line. Vim comes with its advantages: it is powerful, customizable, and fast. Here are some reasons why you should consider learning Vim:</p>
<ul>
<li><p>Most servers are accessed via a CLI, so in system administration, you don't necessarily have the luxury of a GUI. But Vim has got your back – it'll always be there.</p>
</li>
<li><p>Vim uses a keyboard-centric approach, as it is designed to be used without a mouse, which can significantly speed up editing tasks once you have learned the keyboard shortcuts. This also makes it faster than GUI tools.</p>
</li>
<li><p>Some Linux utilities, for example editing cron jobs, work in the same editing format as Vim.</p>
</li>
<li><p>Vim is suitable for all – beginners and advanced users. Vim supports complex string searches, highlighting searches, and much more. Through plugins, Vim provides extended capabilities to developers and system admins that includes code completion, syntax highlighting, file management, version control, and more.</p>
</li>
</ul>
<p>Vim has two variations: Vim (<code>vim</code>) and Vim tiny (<code>vi</code>). Vim tiny is a smaller version of Vim that lacks some features of Vim.</p>
<h4 id="heading-how-to-start-using-vim">How to start using <code>vim</code></h4>
<p>Start using Vim with this command:</p>
<pre><code class="lang-bash">vim your-file.txt
</code></pre>
<p><code>your-file.txt</code> can either be a new file or an existing file that you want to edit.</p>
<h4 id="heading-navigating-vim-mastering-movement-and-command-modes">Navigating Vim: Mastering movement and command modes</h4>
<p>In the early days of the CLI, the keyboards didn't have arrow keys. Hence, navigation was done using the set of available keys, <code>hjkl</code> being one of them.</p>
<p>Being keyboard-centric, using <code>hjkl</code> keys can greatly speed up text editing tasks.</p>
<p>Note: Although arrow keys would work totally fine, you can still experiment with <code>hjkl</code> keys to navigate. Some people find this this way of navigation efficient.</p>
<p>💡<strong>Tip:</strong> To remember the <code>hjkl</code> sequence, use this: <strong>h</strong>ang back, <strong>j</strong>ump down, <strong>k</strong>ick up, <strong>l</strong>eap forward.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719392462442/1a667ede-5f03-4acb-b40f-b10cefc64de3.png" alt="hjkl navigation guide" class="image--center mx-auto" width="471" height="274" loading="lazy"></p>
<h4 id="heading-the-three-vim-modes">The three Vim modes</h4>
<p>You need to know the 3 operating modes of Vim and how to switch between them. Keystrokes behave differently in each command mode. The three modes are as follows:</p>
<ol>
<li><p>Command mode.</p>
</li>
<li><p>Edit mode.</p>
</li>
<li><p>Visual mode.</p>
</li>
</ol>
<p><strong>Command Mode.</strong> When you start Vim, you land in the command mode by default. This mode allows you to access other modes.</p>
<p>⚠ To switch to other modes, you need to be present in the command mode first</p>
<p><strong>Edit Mode</strong></p>
<p>This mode allows you to make changes to the file. To enter edit mode, press <code>I</code> while in command mode. Note the <code>'-- INSERT'</code> switch at the end of the screen.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719392526710/d44cecd7-64be-4c89-9a31-dbf395b77fcb.png" alt="Insert mode in Vim" class="image--center mx-auto" width="433" height="345" loading="lazy"></p>
<p><strong>Visual mode</strong></p>
<p>This mode allows you to work on a single character, a block of text, or lines of text. Let's break it down into simple steps. Remember, use the below combinations when in command mode.</p>
<ul>
<li><p><code>Shift + V</code> → Select multiple lines.</p>
</li>
<li><p><code>Ctrl + V</code> → Block mode</p>
</li>
<li><p><code>V</code> → Character mode</p>
</li>
</ul>
<p>The visual mode comes in handy when you need to copy and paste or edit lines in bulk.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719392557097/b61a1515-cac0-4470-856b-b2c15de581e8.gif" alt="Selectind text using visual mode" class="image--center mx-auto" width="673" height="422" loading="lazy"></p>
<p><strong>Extended command mode.</strong></p>
<p>The extended command mode allows you to perform advanced operations like searching, setting line numbers, and highlighting text. We'll cover extended mode in the next section.</p>
<p>How to stay on track? If you forget your current mode, just press <code>ESC</code> twice and you will be back in Command Mode.</p>
<h4 id="heading-editing-efficiently-in-vim-copypasting-and-searching">Editing Efficiently in Vim: Copy/pasting and searching</h4>
<p><strong>1. How to copy and paste in Vim</strong></p>
<p>Copy-paste is known as 'yank' and 'put' in Linux terms. To copy-paste, follow these steps:</p>
<ul>
<li><p>Select text in visual mode.</p>
</li>
<li><p>Press <code>'y'</code> to copy/ yank.</p>
</li>
<li><p>Move your cursor to the required position and press <code>'p'</code>.</p>
</li>
</ul>
<p><strong>2. How to search for text in Vim</strong></p>
<p>Any series of strings can be searched with Vim using the <code>/</code> in command mode. To search, use <code>/string-to-match</code>.</p>
<p>In the command mode, type <code>:set hls</code> and press <code>enter</code>. Search using <code>/string-to-match</code>. This will highlight the searches.</p>
<p>Let's search a few strings:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719392684097/11c4a45e-0698-4fb7-bef7-f193684ea21a.gif" alt="Highlighting searches in Vim" class="image--center mx-auto" width="800" height="409" loading="lazy"></p>
<p><strong>3. How to exit Vim</strong></p>
<p>First, move to command mode (by pressing escape twice) and then use these flags:</p>
<ul>
<li><p>Exit without saving → <code>:q!</code></p>
</li>
<li><p>Exit and save → <code>:wq!</code></p>
</li>
</ul>
<h4 id="heading-shortcuts-in-vim-making-editing-faster">Shortcuts in Vim: Making Editing Faster</h4>
<p>Note: All these shortcuts work in the command mode only.</p>
<ul>
<li><p><strong>Basic Navigation</strong></p>
<ul>
<li><p><code>h</code>: Move left</p>
</li>
<li><p><code>j</code>: Move down</p>
</li>
<li><p><code>k</code>: Move up</p>
</li>
<li><p><code>l</code>: Move right</p>
</li>
<li><p><code>0</code>: Move to the beginning of the line</p>
</li>
<li><p><code>$</code>: Move to the end of the line</p>
</li>
<li><p><code>gg</code>: Move to the beginning of the file</p>
</li>
<li><p><code>G</code>: Move to the end of the file</p>
</li>
<li><p><code>Ctrl+d</code>: Move half-page down</p>
</li>
<li><p><code>Ctrl+u</code>: Move half-page up</p>
</li>
</ul>
</li>
<li><p><strong>Editing</strong></p>
<ul>
<li><p><code>i</code>: Enter insert mode before the cursor</p>
</li>
<li><p><code>I</code>: Enter insert mode at the beginning of the line</p>
</li>
<li><p><code>a</code>: Enter insert mode after the cursor</p>
</li>
<li><p><code>A</code>: Enter insert mode at the end of the line</p>
</li>
<li><p><code>o</code>: Open a new line below the current line and enter insert mode</p>
</li>
<li><p><code>O</code>: Open a new line above the current line and enter insert mode</p>
</li>
<li><p><code>x</code>: Delete the character under the cursor</p>
</li>
<li><p><code>dd</code>: Delete the current line</p>
</li>
<li><p><code>yy</code>: Yank (copy) the current line (use this in visual mode)</p>
</li>
<li><p><code>p</code>: Paste below the cursor</p>
</li>
<li><p><code>P</code>: Paste above the cursor</p>
</li>
</ul>
</li>
<li><p><strong>Searching and Replacing</strong></p>
<ul>
<li><p><code>/</code>: Search for a pattern which will take you to its next occurrence</p>
</li>
<li><p><code>?</code>: Search for a pattern that will take you to its previous occurrence</p>
</li>
<li><p><code>n</code>: Repeat the last search in the same direction</p>
</li>
<li><p><code>N</code>: Repeat the last search in the opposite direction</p>
</li>
<li><p><code>:%s/old/new/g</code>: Replace all occurrences of <code>old</code> with <code>new</code> in the file</p>
</li>
</ul>
</li>
<li><p><strong>Exiting</strong></p>
<ul>
<li><p><code>:w</code>: Save the file but don't exit</p>
</li>
<li><p><code>:q</code>: Quit Vim (fails if there are unsaved changes)</p>
</li>
<li><p><code>:wq</code> or <code>:x</code>: Save and quit</p>
</li>
<li><p><code>:q!</code>: Quit without saving</p>
</li>
</ul>
</li>
<li><p><strong>Multiple Windows</strong></p>
<ul>
<li><p><code>:split</code> or <code>:sp</code>: Split the window horizontally</p>
</li>
<li><p><code>:vsplit</code> or <code>:vsp</code>: Split the window vertically</p>
</li>
<li><p><code>Ctrl+w followed by h/j/k/l</code>: Navigate between split windows</p>
</li>
</ul>
</li>
</ul>
<h3 id="heading-52-mastering-nano">5.2. Mastering Nano</h3>
<h4 id="heading-getting-started-with-nano-the-user-friendly-text-editor">Getting started with Nano: The user-friendly text editor</h4>
<p>Nano is a user-friendly text editor that is easy to use and is perfect for beginners. It is pre-installed on most Linux distributions.</p>
<p>To create a new file using Nano, use the following command:</p>
<pre><code class="lang-bash">nano
</code></pre>
<p>To start editing an existing file with Nano, use the following command:</p>
<pre><code class="lang-bash">nano filename
</code></pre>
<h4 id="heading-list-of-key-bindings-in-nano">List of key bindings in Nano</h4>
<p>Let's study the most important key bindings in Nano. You'll use the key bindings to perform various operations like saving, exiting, copying, pasting, and more.</p>
<p><strong>Write to a file and save</strong></p>
<p>Once you open Nano using the <code>nano</code> command, you can start writing text. To save the file, press <code>Ctrl+O</code>. You'll be prompted to enter the file name. Press <code>Enter</code> to save the file.</p>
<p><strong>Exit nano</strong></p>
<p>You can exit Nano by pressing <code>Ctrl+X</code>. If you have unsaved changes, Nano will prompt you to save the changes before exiting.</p>
<p><strong>Copying and pasting</strong></p>
<p>To select a region, use <code>ALT+A</code>. A marker will show. Use arrows to select the text. Once selected, exit the marker with with <code>ALT+^</code>.</p>
<p>To copy the selected text, press <code>Ctrl+K</code>. To paste the copied text, press <code>Ctrl+U</code>.</p>
<p><strong>Cutting and pasting</strong></p>
<p>Select the region with <code>ALT+A</code>. Once selected, cut the text with <code>Ctrl+K</code>. To paste the cut text, press <code>Ctrl+U</code>.</p>
<p><strong>Navigation</strong></p>
<p>Use <code>Alt \</code> to move to the beginning of the file.</p>
<p>Use <code>Alt /</code> to move to the end of the file.</p>
<p><strong>Viewing line numbers</strong></p>
<p>When you open a file with <code>nano -l filename</code>, you can view line numbers on the left side of the file.</p>
<p><strong>Searching</strong></p>
<p>You can search for a specific line number with <code>ALt + G</code>. Enter the line number to the prompt and press <code>Enter</code>.</p>
<p>You can also initiate search for a string with <code>CTRL + W</code> and press Enter. If you want to search backwards, you can press <code>Alt+W</code> after initiating the search with <code>Ctrl+W</code>.</p>
<h4 id="heading-summary-of-keybindings-in-nano">Summary of keybindings in Nano</h4>
<ul>
<li><p><strong>General</strong></p>
<ul>
<li><p><code>Ctrl+X</code>: Exit Nano (prompting to save if changes are made)</p>
</li>
<li><p><code>Ctrl+O</code>: Save the file</p>
</li>
<li><p><code>Ctrl+R</code>: Read a file into the current file</p>
</li>
<li><p><code>Ctrl+G</code>: Display the help text</p>
</li>
</ul>
</li>
<li><p><strong>Editing</strong></p>
<ul>
<li><p><code>Ctrl+K</code>: Cut the current line and store it in the cutbuffer</p>
</li>
<li><p><code>Ctrl+U</code>: Paste the contents of the cutbuffer into the current line</p>
</li>
<li><p><code>Alt+6</code>: Copy the current line and store it in the cutbuffer</p>
</li>
<li><p><code>Ctrl+J</code>: Justify the current paragraph</p>
</li>
</ul>
</li>
<li><p><strong>Navigation</strong></p>
<ul>
<li><p><code>Ctrl+A</code>: Move to the beginning of the line</p>
</li>
<li><p><code>Ctrl+E</code>: Move to the end of the line</p>
</li>
<li><p><code>Ctrl+C</code>: Display the current line number and file information</p>
</li>
<li><p><code>Ctrl+_</code> (<code>Ctrl+Shift+-</code>): Go to a specific line (and optionally, column) number</p>
</li>
<li><p><code>Ctrl+Y</code>: Scroll up one page</p>
</li>
<li><p><code>Ctrl+V</code>: Scroll down one page</p>
</li>
</ul>
</li>
<li><p><strong>Search and Replace</strong></p>
<ul>
<li><p><code>Ctrl+W</code>: Search for a string (then <code>Enter</code> to search again)</p>
</li>
<li><p><code>Alt+W</code>: Repeat the last search but in the opposite direction</p>
</li>
<li><p><code>Ctrl+\</code>: Search and replace</p>
</li>
</ul>
</li>
<li><p><strong>Miscellaneous</strong></p>
<ul>
<li><p><code>Ctrl+T</code>: Invoke the spell checker, if available</p>
</li>
<li><p><code>Ctrl+D</code>: Delete the character under the cursor (does not cut it)</p>
</li>
<li><p><code>Ctrl+L</code>: Refresh (redraw) the current screen</p>
</li>
<li><p><code>Alt+U</code>: Undo the last operation</p>
</li>
<li><p><code>Alt+E</code>: Redo the last undone operation</p>
</li>
</ul>
</li>
</ul>
<h2 id="heading-part-6-bash-scripting">Part 6: Bash Scripting</h2>
<h3 id="heading-61-definition-of-bash-scripting">6.1. Definition of Bash scripting</h3>
<p>A bash script is a file containing a sequence of commands that are executed by the bash program line by line. It allows you to perform a series of actions, such as navigating to a specific directory, creating a folder, and launching a process using the command line.</p>
<p>By saving commands in a script, you can repeat the same sequence of steps multiple times and execute them by running the script.</p>
<h3 id="heading-62-advantages-of-bash-scripting">6.2. Advantages of Bash Scripting</h3>
<p>Bash scripting is a powerful and versatile tool for automating system administration tasks, managing system resources, and performing other routine tasks in Unix/Linux systems.</p>
<p>Some advantages of shell scripting are:</p>
<ul>
<li><p><strong>Automation</strong>: Shell scripts allow you to automate repetitive tasks and processes, saving time and reducing the risk of errors that can occur with manual execution.</p>
</li>
<li><p><strong>Portability</strong>: Shell scripts can be run on various platforms and operating systems, including Unix, Linux, macOS, and even Windows through the use of emulators or virtual machines.</p>
</li>
<li><p><strong>Flexibility</strong>: Shell scripts are highly customizable and can be easily modified to suit specific requirements. They can also be combined with other programming languages or utilities to create more powerful scripts.</p>
</li>
<li><p><strong>Accessibility</strong>: Shell scripts are easy to write and don't require any special tools or software. They can be edited using any text editor, and most operating systems have a built-in shell interpreter.</p>
</li>
<li><p><strong>Integration</strong>: Shell scripts can be integrated with other tools and applications, such as databases, web servers, and cloud services, allowing for more complex automation and system management tasks.</p>
</li>
<li><p><strong>Debugging</strong>: Shell scripts are easy to debug, and most shells have built-in debugging and error-reporting tools that can help identify and fix issues quickly.</p>
</li>
</ul>
<h3 id="heading-63-overview-of-bash-shell-and-command-line-interface">6.3. Overview of Bash Shell and Command Line Interface</h3>
<p>The terms "shell" and "bash" are often used interchangeably. But there is a subtle difference between the two.</p>
<p>The term "shell" refers to a program that provides a command-line interface for interacting with an operating system. Bash (Bourne-Again SHell) is one of the most commonly used Unix/Linux shells and is the default shell in many Linux distributions.</p>
<p>Till now, the commands that you have been entering were basically being entered in a "shell".</p>
<p>Although Bash is a type of shell, there are other shells available as well, such as Korn shell (ksh), C shell (csh), and Z shell (zsh). Each shell has its own syntax and set of features, but they all share the common purpose of providing a command-line interface for interacting with the operating system.</p>
<p>You can determine your shell type using the <code>ps</code> command:</p>
<pre><code class="lang-markdown">ps
<span class="hljs-section"># output:</span>

<span class="hljs-code">    PID TTY          TIME CMD
  20506 pts/0    00:00:00 bash &lt;--- the shell type
  20931 pts/0    00:00:00 ps</span>
</code></pre>
<p>In summary, while "shell" is a broad term that refers to any program that provides a command-line interface, "Bash" is a specific type of shell that is widely used in Unix/Linux systems.</p>
<p>Note: In this section, we will be using the "bash" shell.</p>
<h3 id="heading-64-how-to-create-and-execute-bash-scripts">6.4. How to Create and Execute Bash scripts</h3>
<p><strong>Script naming conventions</strong></p>
<p>By naming convention, bash scripts end with <code>.sh</code>. However, bash scripts can run perfectly fine without the <code>sh</code> extension.</p>
<p><strong>Adding the Shebang</strong></p>
<p>Bash scripts start with a <code>shebang</code>. Shebang is a combination of <code>bash #</code> and <code>bang !</code> followed by the bash shell path. This is the first line of the script. Shebang tells the shell to execute it via bash shell. Shebang is simply an absolute path to the bash interpreter.</p>
<p>Below is an example of the shebang statement.</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
</code></pre>
<p>You can find your bash shell path (which may vary from the above) using the command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">which</span> bash
</code></pre>
<p><strong>Creating your first bash script</strong></p>
<p>Our first script prompts the user to enter a path. In return, its contents will be listed.</p>
<p>Create a file named <code>run_all.sh</code> using any editor of your choice.</p>
<pre><code class="lang-bash">vim run_all.sh
</code></pre>
<p>Add the following commands in your file and save it:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Today is "</span> `date`

<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"\nenter the path to directory"</span>
<span class="hljs-built_in">read</span> the_path

<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"\n you path has the following files and folders: "</span>
ls <span class="hljs-variable">$the_path</span>
</code></pre>
<p>Let's take a deeper look at the script line by line. I am displaying the same script again, but this time with line numbers.</p>
<pre><code class="lang-bash">  1 <span class="hljs-comment">#!/bin/bash</span>
  2 <span class="hljs-built_in">echo</span> <span class="hljs-string">"Today is "</span> `date`
  3
  4 <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"\nenter the path to directory"</span>
  5 <span class="hljs-built_in">read</span> the_path
  6
  7 <span class="hljs-built_in">echo</span> -e <span class="hljs-string">"\n you path has the following files and folders: "</span>
  8 ls <span class="hljs-variable">$the_path</span>
</code></pre>
<ul>
<li><p>Line #1: The shebang (<code>#!/bin/bash</code>) points toward the bash shell path.</p>
</li>
<li><p>Line #2: The <code>echo</code> command displays the current date and time on the terminal. Note that the <code>date</code> is in backticks.</p>
</li>
<li><p>Line #4: We want the user to enter a valid path.</p>
</li>
<li><p>Line #5: The <code>read</code> command reads the input and stores it in the variable <code>the_path</code>.</p>
</li>
<li><p>line #8: The <code>ls</code> command takes the variable with the stored path and displays the current files and folders.</p>
</li>
</ul>
<p><strong>Executing the bash script</strong></p>
<p>To make the script executable, assign execution rights to your user using this command:</p>
<pre><code class="lang-bash">chmod u+x run_all.sh
</code></pre>
<p>Here,</p>
<ul>
<li><p><code>chmod</code> modifies the ownership of a file for the current user :<code>u</code>.</p>
</li>
<li><p><code>+x</code> adds the execution rights to the current user. This means that the user who is the owner can now run the script.</p>
</li>
<li><p><code>run_all.sh</code> is the file we wish to run.</p>
</li>
</ul>
<p>You can run the script using any of the mentioned methods:</p>
<ul>
<li><p><code>sh run_all.sh</code></p>
</li>
<li><p><code>bash run_all.sh</code></p>
</li>
<li><p><code>./run_all.sh</code></p>
</li>
</ul>
<p>Let's see it running in action 🚀</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/run-script-bash-2.gif" alt="Running a bash script" width="600" height="400" loading="lazy"></p>
<h3 id="heading-65-bash-scripting-basics">6.5. Bash Scripting Basics</h3>
<h4 id="heading-comments-in-bash-scripting">Comments in bash scripting</h4>
<p>Comments start with a <code>#</code> in bash scripting. This means that any line that begins with a <code>#</code> is a comment and will be ignored by the interpreter.</p>
<p>Comments are very helpful in documenting the code, and it is a good practice to add them to help others understand the code.</p>
<p>These are examples of comments:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># This is an example comment</span>
<span class="hljs-comment"># Both of these lines will be ignored by the interpreter</span>
</code></pre>
<h4 id="heading-variables-and-data-types-in-bash">Variables and data types in Bash</h4>
<p>Variables let you store data. You can use variables to read, access, and manipulate data throughout your script.</p>
<p>There are no data types in Bash. In Bash, a variable is capable of storing numeric values, individual characters, or strings of characters.</p>
<p>In Bash, you can use and set the variable values in the following ways:</p>
<ol>
<li>Assign the value directly:</li>
</ol>
<pre><code class="lang-bash">country=Netherlands
</code></pre>
<p>2.  Assign the value based on the output obtained from a program or command, using command substitution. Note that <code>$</code> is required to access an existing variable's value.</p>
<pre><code class="lang-bash">same_country=<span class="hljs-variable">$country</span>
</code></pre>
<p>This assigns the value of <code>country</code> to the new variable <code>same_country</code>.</p>
<p>To access the variable value, append <code>$</code> to the variable name.</p>
<pre><code class="lang-bash">country=Netherlands
<span class="hljs-built_in">echo</span> <span class="hljs-variable">$country</span>
<span class="hljs-comment"># output</span>
Netherlands
new_country=<span class="hljs-variable">$country</span>
<span class="hljs-built_in">echo</span> <span class="hljs-variable">$new_country</span>
<span class="hljs-comment"># output</span>
Netherlands
</code></pre>
<p>Above, you can see an example of assigning and printing variable values.</p>
<h4 id="heading-variable-naming-conventions">Variable naming conventions</h4>
<p>In Bash scripting, the following are the variable naming conventions:</p>
<ol>
<li><p>Variable names should start with a letter or an underscore (<code>_</code>).</p>
</li>
<li><p>Variable names can contain letters, numbers, and underscores (<code>_</code>).</p>
</li>
<li><p>Variable names are case-sensitive.</p>
</li>
<li><p>Variable names should not contain spaces or special characters.</p>
</li>
<li><p>Use descriptive names that reflect the purpose of the variable.</p>
</li>
<li><p>Avoid using reserved keywords, such as <code>if</code>, <code>then</code>, <code>else</code>, <code>fi</code>, and so on as variable names.</p>
</li>
</ol>
<p>Here are some examples of valid variable names in Bash:</p>
<pre><code class="lang-bash">name
count
_var
myVar
MY_VAR
</code></pre>
<p>And here are some examples of invalid variable names:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># invalid variable names</span>

2ndvar (variable name starts with a number)
my var (variable name contains a space)
my-var (variable name contains a hyphen)
</code></pre>
<p>Following these naming conventions helps make Bash scripts more readable and easier to maintain.</p>
<h4 id="heading-input-and-output-in-bash-scripts">Input and output in Bash scripts</h4>
<h4 id="heading-gathering-input">Gathering input</h4>
<p>In this section, we'll discuss some methods to provide input to our scripts.</p>
<ol>
<li>Reading the user input and storing it in a variable</li>
</ol>
<p>We can read the user input using the <code>read</code> command.</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"What's your name?"</span>
<span class="hljs-built_in">read</span> entered_name
<span class="hljs-built_in">echo</span> -e <span class="hljs-string">"\nWelcome to bash tutorial"</span> <span class="hljs-variable">$entered_name</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/name-sh.gif" alt="Reading the name from a script" width="600" height="400" loading="lazy"></p>
<p>2.  Reading from a file</p>
<p>This code reads each line from a file named <code>input.txt</code> and prints it to the terminal. We'll study while loops later in this section.</p>
<pre><code class="lang-bash"><span class="hljs-keyword">while</span> <span class="hljs-built_in">read</span> line
<span class="hljs-keyword">do</span>
  <span class="hljs-built_in">echo</span> <span class="hljs-variable">$line</span>
<span class="hljs-keyword">done</span> &lt; input.txt
</code></pre>
<p>3.  Command line arguments</p>
<p>In a bash script or function, <code>$1</code> denotes the initial argument passed, <code>$2</code> denotes the second argument passed, and so forth.</p>
<p>This script takes a name as a command-line argument and prints a personalized greeting.</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello, <span class="hljs-variable">$1</span>!"</span>
</code></pre>
<p>We have supplied <code>Zaira</code> as our argument to the script.</p>
<p><strong>Output:</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/name-sh-1.gif" alt="Providing arguments to the bash script" width="600" height="400" loading="lazy"></p>
<h4 id="heading-displaying-output">Displaying output</h4>
<p>Here we'll discuss some methods to receive output from the scripts.</p>
<ol>
<li>Printing to the terminal:</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello, World!"</span>
</code></pre>
<p>This prints the text "Hello, World!" to the terminal.</p>
<p>2.  Writing to a file:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"This is some text."</span> &gt; output.txt
</code></pre>
<p>This writes the text "This is some text." to a file named <code>output.txt</code>. Note that the <code>&gt;</code> operator overwrites a file if it already has some content.</p>
<p>3.  Appending to a file:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"More text."</span> &gt;&gt; output.txt
</code></pre>
<p>This appends the text "More text." to the end of the file <code>output.txt</code>.</p>
<p>4.  Redirecting output:</p>
<pre><code class="lang-bash">ls &gt; files.txt
</code></pre>
<p>This lists the files in the current directory and writes the output to a file named <code>files.txt</code>. You can redirect output of any command to a file this way.</p>
<p>You'll learn about output redirection in detail in section 8.5.</p>
<h4 id="heading-conditional-statements-ifelse">Conditional statements (if/else)</h4>
<p>Expressions that produce a boolean result, either true or false, are called conditions. There are several ways to evaluate conditions, including <code>if</code>, <code>if-else</code>, <code>if-elif-else</code>, and nested conditionals.</p>
<p><strong>Syntax</strong>:</p>
<pre><code class="lang-bash"><span class="hljs-keyword">if</span> [[ condition ]];
<span class="hljs-keyword">then</span>
    statement
<span class="hljs-keyword">elif</span> [[ condition ]]; <span class="hljs-keyword">then</span>
    statement 
<span class="hljs-keyword">else</span>
    <span class="hljs-keyword">do</span> this by default
<span class="hljs-keyword">fi</span>
</code></pre>
<h4 id="heading-syntax-of-bash-conditional-statements">Syntax of bash conditional statements</h4>
<p>We can use logical operators such as AND <code>-a</code> and OR <code>-o</code> to make comparisons that have more significance.</p>
<pre><code class="lang-bash"><span class="hljs-keyword">if</span> [ <span class="hljs-variable">$a</span> -gt 60 -a <span class="hljs-variable">$b</span> -lt 100 ]
</code></pre>
<p>This statement checks if both conditions are <code>true</code>: <code>a</code> is greater than <code>60</code> AND <code>b</code> is less than <code>100</code>.</p>
<p>Let's see an example of a Bash script that uses <code>if</code>, <code>if-else</code>, and <code>if-elif-else</code> statements to determine if a user-inputted number is positive, negative, or zero:</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-comment"># Script to determine if a number is positive, negative, or zero</span>

<span class="hljs-built_in">echo</span> <span class="hljs-string">"Please enter a number: "</span>
<span class="hljs-built_in">read</span> num

<span class="hljs-keyword">if</span> [ <span class="hljs-variable">$num</span> -gt 0 ]; <span class="hljs-keyword">then</span>
  <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$num</span> is positive"</span>
<span class="hljs-keyword">elif</span> [ <span class="hljs-variable">$num</span> -lt 0 ]; <span class="hljs-keyword">then</span>
  <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$num</span> is negative"</span>
<span class="hljs-keyword">else</span>
  <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$num</span> is zero"</span>
<span class="hljs-keyword">fi</span>
</code></pre>
<p>The script first prompts the user to enter a number. Then, it uses an <code>if</code> statement to check if the number is greater than <code>0</code>. If it is, the script outputs that the number is positive. If the number is not greater than <code>0</code>, the script moves on to the next statement, which is an <code>if-elif</code> statement.</p>
<p>Here, the script checks if the number is less than <code>0</code>. If it is, the script outputs that the number is negative.</p>
<p>Finally, if the number is neither greater than <code>0</code> nor less than <code>0</code>, the script uses an <code>else</code> statement to output that the number is zero.</p>
<p>Seeing it in action 🚀</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/test-odd.gif" alt="Checking if a number is even or odd" width="600" height="400" loading="lazy"></p>
<h4 id="heading-looping-and-branching-in-bash">Looping and branching in Bash</h4>
<p><strong>While loop</strong></p>
<p>While loops check for a condition and loop until the condition remains <code>true</code>. We need to provide a counter statement that increments the counter to control loop execution.</p>
<p>In the example below, <code>(( i += 1 ))</code> is the counter statement that increments the value of <code>i</code>. The loop will run exactly 10 times.</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>
i=1
<span class="hljs-keyword">while</span> [[ <span class="hljs-variable">$i</span> -le 10 ]] ; <span class="hljs-keyword">do</span>
   <span class="hljs-built_in">echo</span> <span class="hljs-string">"<span class="hljs-variable">$i</span>"</span>
  (( i += 1 ))
<span class="hljs-keyword">done</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-187.png" alt="Looping from 1 to 10 using " width="600" height="400" loading="lazy"></p>
<p><strong>For loop</strong></p>
<p>The <code>for</code> loop, just like the <code>while</code> loop, allows you to execute statements a specific number of times. Each loop differs in its syntax and usage.</p>
<p>In the example below, the loop will iterate 5 times.</p>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> {1..5}
<span class="hljs-keyword">do</span>
    <span class="hljs-built_in">echo</span> <span class="hljs-variable">$i</span>
<span class="hljs-keyword">done</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/03/image-186.png" alt="Looping from 1 to 10 using " width="600" height="400" loading="lazy"></p>
<p><strong>Case statements</strong></p>
<p>In Bash, case statements are used to compare a given value against a list of patterns and execute a block of code based on the first pattern that matches. The syntax for a case statement in Bash is as follows:</p>
<pre><code class="lang-bash"><span class="hljs-keyword">case</span> expression <span class="hljs-keyword">in</span>
    pattern1)
        <span class="hljs-comment"># code to execute if expression matches pattern1</span>
        ;;
    pattern2)
        <span class="hljs-comment"># code to execute if expression matches pattern2</span>
        ;;
    pattern3)
        <span class="hljs-comment"># code to execute if expression matches pattern3</span>
        ;;
    *)
        <span class="hljs-comment"># code to execute if none of the above patterns match expression</span>
        ;;
<span class="hljs-keyword">esac</span>
</code></pre>
<p>Here, "expression" is the value that we want to compare, and "pattern1", "pattern2", "pattern3", and so on are the patterns that we want to compare it against.</p>
<p>The double semicolon ";;" separates each block of code to execute for each pattern. The asterisk "*" represents the default case, which executes if none of the specified patterns match the expression.</p>
<p>Let's see an example:</p>
<pre><code class="lang-bash">fruit=<span class="hljs-string">"apple"</span>

<span class="hljs-keyword">case</span> <span class="hljs-variable">$fruit</span> <span class="hljs-keyword">in</span>
    <span class="hljs-string">"apple"</span>)
        <span class="hljs-built_in">echo</span> <span class="hljs-string">"This is a red fruit."</span>
        ;;
    <span class="hljs-string">"banana"</span>)
        <span class="hljs-built_in">echo</span> <span class="hljs-string">"This is a yellow fruit."</span>
        ;;
    <span class="hljs-string">"orange"</span>)
        <span class="hljs-built_in">echo</span> <span class="hljs-string">"This is an orange fruit."</span>
        ;;
    *)
        <span class="hljs-built_in">echo</span> <span class="hljs-string">"Unknown fruit."</span>
        ;;
<span class="hljs-keyword">esac</span>
</code></pre>
<p>In this example, since the value of <code>fruit</code> is <code>apple</code>, the first pattern matches, and the block of code that echoes <code>This is a red fruit.</code> is executed. If the value of <code>fruit</code> were instead <code>banana</code>, the second pattern would match and the block of code that echoes <code>This is a yellow fruit.</code> would execute, and so on.</p>
<p>If the value of <code>fruit</code> does not match any of the specified patterns, the default case is executed, which echoes <code>Unknown fruit.</code></p>
<h2 id="heading-part-7-managing-software-packages-in-linux">Part 7: Managing Software Packages in Linux</h2>
<p>Linux comes with several built-in programs. But you might need to install new programs based on your needs. You might also need to upgrade the existing applications.</p>
<h3 id="heading-71-packages-and-package-management">7.1. Packages and Package Management</h3>
<h4 id="heading-what-is-a-package">What is a package?</h4>
<p>A package is a collection of files that are bundled together. These files are essential for a particular program to run. These files contain the program's executable files, libraries, and other resources.</p>
<p>In addition to the files required for the program to run, packages also contain installation scripts, which copy the files to where they are needed. A program may contain many files and dependencies. With packages, it is easier to manage all the files and dependencies at once.</p>
<h4 id="heading-what-is-the-difference-between-source-and-binary">What is the difference between source and binary?</h4>
<p>Programmers write source code in a programming language. This source code is then compiled into machine code that the computer can understand. The compiled code is called binary code.</p>
<p>When you download a package, you can either get the <em>source code</em> or the <em>binary code.</em> The source code is the human-readable code that can be compiled into binary code. The binary code is the compiled code that the computer can understand.</p>
<p>Source packages can be used with any type of machine if the source code is compiled properly. Binary, on the other hand, is compiled code that is specific to a particular type of machine or architecture.</p>
<p>You can find the architecture of your machine using the <code>uname -m</code> command.</p>
<pre><code class="lang-bash">uname -m
<span class="hljs-comment"># output</span>
x86_64
</code></pre>
<h4 id="heading-package-dependencies">Package dependencies</h4>
<p>Programs often share files. Instead of including these files in each package, a separate package can provide them for all programs.</p>
<p>To install a program that needs these files, you must also install the package containing them. This is called a package dependency. Specifying dependencies makes packages smaller and simpler by reducing duplicates.</p>
<p>When you install a program, its dependencies must also be installed. Most required dependencies are usually already installed, but a few extra ones might be needed. So, don't be surprised if several other packages are installed along with your chosen package. These are the necessary dependencies.</p>
<h4 id="heading-package-managers">Package managers</h4>
<p>Linux offers a comprehensive package management system for installing, upgrading, configuring, and removing software.</p>
<p>With package management, you can get access to an organized base of thousands of software packages along with having the ability to resolve dependencies and check for software updates.</p>
<p>Packages can be managed using either command-line utilities that can be easily automated by system administrators, or through a graphical interface.</p>
<h4 id="heading-software-channelsrepositories">Software channels/repositories</h4>
<p>⚠️ Package management is different for different distros. Here, we are using Ubuntu.</p>
<p>Installing software is a bit different in Linux as compared to Windows and Mac.</p>
<p>Linux uses repositories to store software packages. A repository is a collection of software packages that are available for installation via a package manager.</p>
<p>A package manager also stores an index of all of the packages available from a repo. Sometimes the index is rebuilt to ensure that it is up to date and to know which packages have been upgraded or added to the channel since it last checked.</p>
<p>The generic process of downloading software from a repo looks something like this:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719313472889/f4961606-b9c4-4ed7-8edc-61e0fc6908e4.png" alt="Rrocess of downloading software from a remote repo" class="image--center mx-auto" width="1080" height="1080" loading="lazy"></p>
<p>If we talk specifically about Ubuntu,</p>
<ol>
<li><p>Index is fetched using <code>apt update.</code> (<code>apt</code> is explained in next section).</p>
</li>
<li><p>Required files/ dependencies requested according to index using <code>apt install</code></p>
</li>
<li><p>Packages and dependencies installed locally.</p>
</li>
<li><p>Update dependencies and packages when required using <code>apt update</code> and <code>apt upgrade</code></p>
</li>
</ol>
<p>On Debian-based distros, you can file the list of repos (repositories) in <code>/etc/apt/sources.list</code>.</p>
<h3 id="heading-72-installing-a-package-via-command-line">7.2. Installing a Package via Command Line</h3>
<p>The <code>apt</code> command is a powerful command-line tool, which works with Ubuntu’s "Advanced Packaging Tool (APT)".</p>
<p><code>apt</code>, along with the commands bundled with it, provides the means to install new software packages, upgrade existing software packages, update the package list index, and even upgrade the entire Ubuntu system.</p>
<p>To view the logs of the installation using <code>apt</code>, you can view the <code>/var/log/dpkg.log</code> file.</p>
<p>Following are the uses of the <code>apt</code> command:</p>
<h4 id="heading-installing-packages">Installing packages</h4>
<p>For example, to install the <code>htop</code> package, you can use the following command:</p>
<pre><code class="lang-bash">sudo apt install htop
</code></pre>
<h4 id="heading-updating-the-package-list-index">Updating the package list index</h4>
<p>The package list index is a list of all the packages available in the repositories. To update the local package list index, you can use the following command:</p>
<pre><code class="lang-bash">sudo apt update
</code></pre>
<h4 id="heading-upgrading-the-packages">Upgrading the packages</h4>
<p>Installed packages on your system can get updates containing bug fixes, security patches, and new features.</p>
<p>To upgrade the packages, you can use the following command:</p>
<pre><code class="lang-bash">sudo apt upgrade
</code></pre>
<h4 id="heading-removing-packages">Removing packages</h4>
<p>To remove a package, like <code>htop</code>, you can use the following command:</p>
<pre><code class="lang-bash">sudo apt remove htop
</code></pre>
<h3 id="heading-73-installing-a-package-via-an-advanced-graphical-method-synaptic">7.3. Installing a Package via an Advanced Graphical Method – Synaptic</h3>
<p>If you are not comfortable with the command line, you can use a GUI application to install packages. You can achieve the same results as the command line, but with a graphical interface.</p>
<p>Synaptic is a GUI package management application that helps in listing the installed packages, their status, pending updates, and so on. It offers custom filters to help you narrow down the search results.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719313599636/0f362ed7-c371-4a58-96c2-c359178cdbd9.png" alt="0f362ed7-c371-4a58-96c2-c359178cdbd9" class="image--center mx-auto" width="1356" height="868" loading="lazy"></p>
<p>You can also right-click on a package and view further details like the dependencies, maintainer, size, and the installed files.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719313607397/33b7ad76-2492-4805-8133-35c8cd3c4a0a.png" alt="View a package's detail" class="image--center mx-auto" width="560" height="634" loading="lazy"></p>
<h3 id="heading-74-installing-downloaded-packages-from-a-website">7.4. Installing downloaded packages from a website</h3>
<p>You may want to install a package you have downloaded from a website, rather than from a software repository. These packages are called <code>.deb</code> files.</p>
<p><strong>Using</strong><code>dpkg</code><strong>to install packages:</strong><code>dpkg</code> is a command-line tool used to install packages. To install a package with <strong>dpkg</strong>, open the Terminal and type the following:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> directory
sudo dpkg -i package_name.deb
</code></pre>
<p>Note: Replace "directory" with the directory where the package is stored and "package_name" with the filename of the package.</p>
<p>Alternatively, you can right-click, select "Open With Other Application," and choose a GUI app of your choice.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719322161581/f16d83ac-ca9a-4502-a80c-e6a25dee5c68.png" alt="Installing a software using an app" class="image--center mx-auto" width="534" height="505" loading="lazy"></p>
<p>💡 <strong>Tip:</strong> In Ubuntu, you can see a list of installed packages with <code>dpkg --list</code>.</p>
<h2 id="heading-part-8-advanced-linux-topics">Part 8: Advanced Linux Topics</h2>
<h3 id="heading-81-user-management">8.1. User Management</h3>
<p>There can be multiple users with varying levels of access in a system. In Linux, the root user has the highest level of access and can perform any operation on the system. Regular users have limited access and can only perform operations they have been granted permission to do.</p>
<h4 id="heading-what-is-a-user">What is a user?</h4>
<p>A user account provides separation between different people and programs that can run commands.</p>
<p>Humans identify users by a name, as names are easy to work with. But the system identifies users by a unique number called the user ID (UID).</p>
<p>When human users log in using the provided username, they have to use a password to authorize themselves.</p>
<p>User accounts form the foundations of system security. File ownership is also associated with user accounts and it enforces access control to the files. Every process has an associated user account that provides a layer of control for the admins.</p>
<p>There are three main types of user accounts:</p>
<ol>
<li><p><strong>Superuser</strong>: The superuser has complete access to the system. The name of the superuser is <code>root</code>. It has a <code>UID</code> of 0.</p>
</li>
<li><p><strong>System user</strong>: The system user has user accounts that are used to run system services. These accounts are used to run system services and are not meant for human interaction.</p>
</li>
<li><p><strong>Regular user</strong>: Regular users are human users who have access to the system.</p>
</li>
</ol>
<p>The <code>id</code> command displays the user ID and group ID of the current user.</p>
<pre><code class="lang-bash">id
uid=1000(john) gid=1000(john) groups=1000(john),4(adm),24(cdrom),27(sudo),30(dip)... output truncated
</code></pre>
<p>To view the basic information of another user, pass the username as an argument to the <code>id</code> command.</p>
<pre><code class="lang-bash">id username
</code></pre>
<p>To view user-related information for processes, use the <code>ps</code> command with the <code>-u</code> flag.</p>
<pre><code class="lang-bash">ps -u
<span class="hljs-comment"># Output</span>
USER       PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root         1  0.0  0.1  16968  3920 ?        Ss   18:45   0:00 /sbin/init splash
root         2  0.0  0.0      0     0 ?        S    18:45   0:00 [kthreadd]
</code></pre>
<p>By default, systems use the <code>/etc/passwd</code> file to store user information.</p>
<p>Here is a line from the <code>/etc/passwd</code> file:</p>
<pre><code class="lang-bash">root:x:0:0:root:/root:/bin/bash
</code></pre>
<p>The <code>/etc/passwd</code> file contains the following information about each user:</p>
<ol>
<li><p>Username: <code>root</code> – The username of the user account.</p>
</li>
<li><p>Password: <code>x</code> – The password in encrypted format for the user account that is stored in the <code>/etc/shadow</code> file for security reasons.</p>
</li>
<li><p>User ID (UID): <code>0</code> – The unique numerical identifier for the user account.</p>
</li>
<li><p>Group ID (GID): <code>0</code> – The primary group identifier for the user account.</p>
</li>
<li><p>User Info: <code>root</code> – The real name for the user account.</p>
</li>
<li><p>Home directory: <code>/root</code> – The home directory for the user account.</p>
</li>
<li><p>Shell: <code>/bin/bash</code> – The default shell for the user account. A system user might use <code>/sbin/nologin</code> if interactive logins are not allowed for that user.</p>
</li>
</ol>
<h4 id="heading-what-is-a-group">What is a group?</h4>
<p>A group is a collection of user accounts that share access and resources. Groups have group names to identify them. The system identifies groups by a unique number called the group ID (GID).</p>
<p>By default, the information about groups is stored in the <code>/etc/group</code> file.</p>
<p>Here is an entry from the <code>/etc/group</code> file:</p>
<pre><code class="lang-bash">adm:x:4:syslog,john
</code></pre>
<p>Here is the breakdown of the fields in the given entry:</p>
<ol>
<li><p>Group name: <code>adm</code> – The name of the group.</p>
</li>
<li><p>Password: <code>x</code> – The password for the group is stored in the <code>/etc/gshadow</code> file for security reasons. The password is optional and appears empty if not set.</p>
</li>
<li><p>Group ID (GID): <code>4</code> – The unique numerical identifier for the group.</p>
</li>
<li><p>Group members: <code>syslog,john</code> – The list of usernames that are members of the group. In this case, the group <code>adm</code> has two members: <code>syslog</code> and <code>john</code>.</p>
</li>
</ol>
<p>In this specific entry, the group name is <code>adm</code>, the group ID is <code>4</code>, and the group has two members: <code>syslog</code> and <code>john</code>. The password field is typically set to <code>x</code> to indicate that the group password is stored in the <code>/etc/gshadow</code> file.</p>
<p>The groups are further divided into '<em>primary'</em> and '<em>supplementary'</em> groups.</p>
<ul>
<li><p>Primary Group: Each user is assigned one primary group by default. This group usually has the same name as the user and is created when the user account is made. Files and directories created by the user are typically owned by this primary group.</p>
</li>
<li><p>Supplementary Groups: These are extra groups a user can belong to in addition to their primary group. Users can be members of multiple supplementary groups. These groups let a user have permissions for resources shared among those groups. They help provide access to shared resources without affecting the system’s file permissions and keeping the security intact. While a user must belong to one primary group, belonging to supplementary groups is optional.</p>
</li>
</ul>
<h4 id="heading-access-control-finding-and-understanding-file-permission">Access control: finding and understanding file permission</h4>
<p>File ownership can be viewed using the <code>ls -l</code> command. The first column in the output of the <code>ls -l</code> command shows the permissions of the file. Other columns show the owner of the file and the group that the file belongs to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-146.png" alt="Detailed output of ls -l" width="600" height="400" loading="lazy"></p>
<p>Let's have a closer look into the <code>mode</code> column:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-147.png" alt="Permission classes and file types" width="600" height="400" loading="lazy"></p>
<p><strong>Mode</strong> defines two things:</p>
<ul>
<li><p><strong>File type:</strong> File type defines the type of the file. For regular files that contain simple data it is blank <code>-</code>. For other special file types the symbol is different. For a directory which is a special file, it is <code>d</code>. Special files are treated differently by the OS.</p>
</li>
<li><p><strong>Permission classes:</strong> The next set of characters define the permissions for user, group, and others respectively.<br>  – <strong>User</strong>: This is the owner of a file and owner of the file belongs to this class.<br>  – <strong>Group</strong>: The members of the file’s group belong to this class<br>  – <strong>Other</strong>: Any users that are not part of the user or group classes belong to this class.</p>
</li>
</ul>
<p>💡<strong>Tip:</strong> Directory ownership can be viewed using the <code>ls -ld</code> command.</p>
<h5 id="heading-how-to-read-symbolic-permissions-or-the-rwx-permissions">How to Read Symbolic Permissions or the <code>rwx</code> permissions</h5>
<p>The <code>rwx</code> representation is known as the Symbolic representation of permissions. In the set of permissions,</p>
<ul>
<li><p><code>r</code> stands for <strong>read</strong>. It is indicated in the first character of the triad.</p>
</li>
<li><p><code>w</code> stands for <strong>write</strong>. It is indicated in the second character of the triad.</p>
</li>
<li><p><code>x</code> stands for <strong>execution</strong>. It is indicated in the third character of the triad.</p>
</li>
</ul>
<p><strong>Read:</strong></p>
<p>For regular files, read permissions allow the file to be opened and read only. Users can't modify the file.</p>
<p>Similarly for directories, read permissions allow the listing of directory content without any modification in the directory.</p>
<p><strong>Write:</strong></p>
<p>When files have write permissions, the user can modify (edit, delete) the file and save it.</p>
<p>For folders, write permissions enable a user to modify its contents (create, delete, and rename the files inside it), and modify the contents of files that the user has write permissions to.</p>
<p><strong>Examples of permissions in Linux</strong></p>
<p>Now that we know how to read permissions, let's see some examples.</p>
<ul>
<li><p><code>-rwx------</code>: A file that is only accessible and executable by its owner.</p>
<p>  <code>-rw-rw-r--</code>: A file that is open to modification by its owner and group but not by others.</p>
</li>
<li><p><code>drwxrwx---</code>: A directory that can be modified by its owner and group.</p>
</li>
</ul>
<p><strong>Execute:</strong></p>
<p>For files, execute permissions allows the user to run an executable script. For directories, the user can access them, and access details about files in the directory.</p>
<h5 id="heading-how-to-change-file-permissions-and-ownership-in-linux-using-chmod-and-chown">How to Change File Permissions and Ownership in Linux using <code>chmod</code> and <code>chown</code></h5>
<p>Now that we know the basics of ownerships and permissions, let's see how we can modify permissions using the <code>chmod</code> command.</p>
<p><strong>Syntax of</strong><code>chmod</code>:</p>
<pre><code class="lang-bash">chmod permissions filename
</code></pre>
<p>Where,</p>
<ul>
<li><p><code>permissions</code> can be read, write, execute or a combination of them.</p>
</li>
<li><p><code>filename</code> is the name of the file for which the permissions need to change. This parameter can also be a list if files to change permissions in bulk.</p>
</li>
</ul>
<p>We can change permissions using two modes:</p>
<ol>
<li><p><strong>Symbolic mode</strong>: this method uses symbols like <code>u</code>, <code>g</code>, <code>o</code> to represent users, groups, and others. Permissions are represented as  <code>r, w, x</code> for read, write, and execute, respectively. You can modify permissions using +, - and =.</p>
</li>
<li><p><strong>Absolute mode</strong>: this method represents permissions as 3-digit octal numbers ranging from 0-7.</p>
</li>
</ol>
<p>Now, let's see them in detail.</p>
<h5 id="heading-how-to-change-permissions-using-symbolic-mode">How to Change Permissions using Symbolic Mode</h5>
<p>The table below summarize the user representation:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>USER REPRESENTATION</strong></td><td><strong>DESCRIPTION</strong></td></tr>
</thead>
<tbody>
<tr>
<td>u</td><td>user/owner</td></tr>
<tr>
<td>g</td><td>group</td></tr>
<tr>
<td>o</td><td>other</td></tr>
</tbody>
</table>
</div><p>We can use mathematical operators to add, remove, and assign permissions. The table below shows the summary:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>OPERATOR</strong></td><td><strong>DESCRIPTION</strong></td></tr>
</thead>
<tbody>
<tr>
<td>+</td><td>Adds a permission to a file or directory</td></tr>
<tr>
<td>–</td><td>Removes the permission</td></tr>
<tr>
<td>\=</td><td>Sets the permission if not present before. Also overrides the permissions if set earlier.</td></tr>
</tbody>
</table>
</div><p><strong>Example:</strong></p>
<p>Suppose I have a script and I want to make it executable for the owner of the file <code>zaira</code>.</p>
<p>Current file permissions are as follows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-161.png" alt="image-161" width="600" height="400" loading="lazy"></p>
<p>Let's split the permissions like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-160.png" alt="Splitting file permissions" width="600" height="400" loading="lazy"></p>
<p>To add execution rights (<code>x</code>) to owner (<code>u</code>) using symbolic mode, we can use the command below:</p>
<pre><code class="lang-bash">chmod u+x mymotd.sh
</code></pre>
<p><strong>Output:</strong></p>
<p>Now, we can see that the execution permissions have been added for owner <code>zaira</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-162.png" alt="Permission updated" width="600" height="400" loading="lazy"></p>
<p><strong>Additional examples for changing permissions via symbolic method:</strong></p>
<ul>
<li><p>Removing <code>read</code> and <code>write</code> permission for <code>group</code> and <code>others</code>: <code>chmod go-rw</code>.</p>
</li>
<li><p>Removing <code>read</code> permissions for <code>others</code>: <code>chmod o-r</code>.</p>
</li>
<li><p>Assigning <code>write</code> permission to <code>group</code> and overriding existing permission: <code>chmod g=w</code>.</p>
</li>
</ul>
<h5 id="heading-how-to-change-permissions-using-absolute-mode">How to Change Permissions using Absolute Mode</h5>
<p>Absolute mode uses numbers to represent permissions and mathematical operators to modify them.</p>
<p>The below table shows how we can assign relevant permissions:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>PERMISSION</strong></td><td><strong>PROVIDE PERMISSION</strong></td></tr>
</thead>
<tbody>
<tr>
<td>read</td><td>add 4</td></tr>
<tr>
<td>write</td><td>add 2</td></tr>
<tr>
<td>execute</td><td>add 1</td></tr>
</tbody>
</table>
</div><p>Permissions can be revoked using subtraction. The below table shows how you can remove relevant permissions.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>PERMISSION</strong></td><td><strong>REVOKE PERMISSION</strong></td></tr>
</thead>
<tbody>
<tr>
<td>read</td><td>subtract 4</td></tr>
<tr>
<td>write</td><td>subtract 2</td></tr>
<tr>
<td>execute</td><td>subtract 1</td></tr>
</tbody>
</table>
</div><p><strong>Example</strong>:</p>
<ul>
<li>Set <code>read</code> (add 4) for <code>user</code>, <code>read</code> (add 4) and <code>execute</code> (add 1) for group, and only <code>execute</code> (add 1) for others.</li>
</ul>
<p><code>chmod 451 file-name</code></p>
<p>This is how we performed the calculation:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-163.png" alt="Calculation breakdown for adding permissions" width="600" height="400" loading="lazy"></p>
<p>Note that this is the same as <code>r--r-x--x</code>.</p>
<ul>
<li>Remove <code>execution</code> rights from <code>other</code> and <code>group</code>.</li>
</ul>
<p>To remove execution from <code>other</code> and <code>group</code>, subtract 1 from the execute part of last 2 octets.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-164.png" alt="Calculation breakdown for removing permissions" width="600" height="400" loading="lazy"></p>
<ul>
<li>Assign <code>read</code>, <code>write</code> and <code>execute</code> to <code>user</code>, <code>read</code> and <code>execute</code> to <code>group</code> and only <code>read</code> to others.</li>
</ul>
<p>This would be the same as <code>rwxr-xr--</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-165.png" alt="Calculation breakdown for adding permissions" width="600" height="400" loading="lazy"></p>
<h5 id="heading-how-to-change-ownership-using-the-chown-command">How to Change Ownership using the <code>chown</code> Command</h5>
<p>Next, we will learn how to change the ownership of a file. You can change the ownership of a file or folder using the <code>chown</code> command. In some cases, changing ownership requires <code>sudo</code> permissions.</p>
<p>Syntax of <code>chown</code>:</p>
<pre><code class="lang-bash">chown user filename
</code></pre>
<h5 id="heading-how-to-change-user-ownership-with-chown">How to change user ownership with <code>chown</code></h5>
<p>Let's transfer the ownership from user <code>zaira</code> to user <code>news</code>.</p>
<p><code>chown news mymotd.sh</code></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-167.png" alt="view current owner" width="600" height="400" loading="lazy"></p>
<p>Command to change ownership: <code>sudo chown news mymotd.sh</code>.</p>
<p><strong>Output:</strong></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2022/04/image-168.png" alt="Ownership changed" width="600" height="400" loading="lazy"></p>
<h5 id="heading-how-to-change-user-and-group-ownership-simultaneously">How to change user and group ownership simultaneously</h5>
<p>We can also use <code>chown</code> to change user and group simultaneously.</p>
<pre><code class="lang-bash">chown user:group filename
</code></pre>
<h5 id="heading-how-to-change-directory-ownership">How to change directory ownership</h5>
<p>You can change ownership recursively for contents in a directory. The example below changes the ownership of the <code>/opt/script</code> folder to allow user <code>admin</code>.</p>
<pre><code class="lang-bash">chown -R admin /opt/script
</code></pre>
<h5 id="heading-how-to-change-group-ownership">How to change group ownership</h5>
<p>In case we only need to change the group owner, we can use <code>chown</code> by preceding the group name by a colon <code>:</code></p>
<pre><code class="lang-bash">chown :admins /opt/script
</code></pre>
<h5 id="heading-how-to-switch-between-users">How to switch between users</h5>
<p>You can switch between users using the <code>su</code> command.</p>
<pre><code class="lang-bash">[user01@host ~]$ su user02
Password:
[user02@host ~]$
</code></pre>
<h5 id="heading-how-to-gain-superuser-access">How to gain superuser access</h5>
<p>The superuser or the root user has the highest level of access on a Linux system. The root user can perform any operation on the system. The root user can access all files and directories, install and remove software, and modify or override system configurations.</p>
<p>With great power comes great responsibility. If the root user is compromised, someone can gain complete control over the system. It is advised to use the root user account only when necessary.</p>
<p>If you omit the username, the <code>su</code> command switches to the root user account by default.</p>
<pre><code class="lang-bash">[user01@host ~]$ su
Password:
[root@host ~]<span class="hljs-comment">#</span>
</code></pre>
<p>Another variation of the <code>su</code> command is <code>su -</code>. The <code>su</code> command switches to the root user account but does not change the environment variables. The <code>su -</code> command switches to the root user account and changes the environment variables to those of the target user.</p>
<h5 id="heading-running-commands-with-sudo">Running commands with sudo</h5>
<p>To run commands as the <code>root</code> user without switching to the <code>root</code> user account, you can use the <code>sudo</code> command. The <code>sudo</code> command allows you to run commands with elevated privileges.</p>
<p>Running commands with <code>sudo</code> is a safer option rather than running the commands as the <code>root</code> user. This is because, only a specific set of users can be granted permission to run commands with <code>sudo</code>. This is defined in the <code>/etc/sudoers</code> file.</p>
<p>Also, <code>sudo</code> logs all commands that are run with it, providing an audit trail of who ran which commands and when.</p>
<p>In Ubuntu, you can find the audit logs here:</p>
<pre><code class="lang-bash">cat /var/<span class="hljs-built_in">log</span>/auth.log | grep sudo
</code></pre>
<p>For a user that does not have access to <code>sudo</code>, it gets flagged in logs and prompts a message like this:</p>
<pre><code class="lang-bash">user01 is not <span class="hljs-keyword">in</span> the sudoers file.  This incident will be reported.
</code></pre>
<h4 id="heading-managing-local-user-accounts">Managing local user accounts</h4>
<h5 id="heading-creating-users-from-the-command-line">Creating users from the command line</h5>
<p>The command used to add a new user is:</p>
<pre><code class="lang-bash">sudo useradd username
</code></pre>
<p>This command sets up a user's home directory and creates a private group designated by the user's username. Currently, the account lacks a valid password, preventing the user from logging in until a password is created.</p>
<h5 id="heading-modifying-existing-users">Modifying existing users</h5>
<p>The <code>usermod</code> command is used to modify existing users. Here are some of the common options used with the <code>usermod</code> command:</p>
<p>Here are some examples of the <code>usermod</code> command in Linux:</p>
<ol>
<li><p><strong>Change a user's login name:</strong></p>
<pre><code class="lang-bash"> sudo usermod -l newusername oldusername
</code></pre>
</li>
<li><p><strong>Change a user's home directory:</strong></p>
<pre><code class="lang-bash"> sudo usermod -d /new/home/directory -m username
</code></pre>
</li>
<li><p><strong>Add a user to a supplementary group:</strong></p>
<pre><code class="lang-bash"> sudo usermod -aG groupname username
</code></pre>
</li>
<li><p><strong>Change a user's shell:</strong></p>
<pre><code class="lang-bash"> sudo usermod -s /bin/bash username
</code></pre>
</li>
<li><p><strong>Lock a user's account:</strong></p>
<pre><code class="lang-bash"> sudo usermod -L username
</code></pre>
</li>
<li><p><strong>Unlock a user's account:</strong></p>
<pre><code class="lang-bash"> sudo usermod -U username
</code></pre>
</li>
<li><p><strong>Set an expiration date for a user account:</strong></p>
<pre><code class="lang-bash"> sudo usermod -e YYYY-MM-DD username
</code></pre>
</li>
<li><p><strong>Change a user's user ID (UID):</strong></p>
<pre><code class="lang-bash"> sudo usermod -u newUID username
</code></pre>
</li>
<li><p><strong>Change a user's primary group:</strong></p>
<pre><code class="lang-bash"> sudo usermod -g newgroup username
</code></pre>
</li>
<li><p><strong>Remove a user from a supplementary group:</strong></p>
<pre><code class="lang-bash">sudo gpasswd -d username groupname
</code></pre>
</li>
</ol>
<h5 id="heading-deleting-users">Deleting users</h5>
<p>The <code>userdel</code> command is used to delete a user account and related files from the system.</p>
<ul>
<li><p><code>sudo userdel username</code>: removes the user's details from <code>/etc/passwd</code> but keeps the user's home directory.</p>
</li>
<li><p>The <code>sudo userdel -r username</code> command removes the user's details from <code>/etc/passwd</code> and also deletes the user's home directory.</p>
</li>
</ul>
<h5 id="heading-changing-user-passwords">Changing user passwords</h5>
<p>The <code>passwd</code> command is used to change a user's password.</p>
<ul>
<li><code>sudo passwd username</code>: sets the initial password or changes the existing password of username. It is also used to change the password of the currently logged in user.</li>
</ul>
<h3 id="heading-82-connecting-to-remote-servers-via-ssh">8.2 Connecting to Remote Servers via SSH</h3>
<p>Accessing remote servers is one of the essential tasks for system administrators. You can connect to different servers or access databases through your local machine and execute commands, all using SSH.</p>
<p><strong>What is the SSH protocol?</strong></p>
<p>SSH stands for Secure Shell. It is a cryptographic network protocol that allows secure communication between two systems.</p>
<p>The default port for SSH is <code>22</code>.</p>
<p>The two participants while communicating via SSH are:</p>
<ul>
<li><p>The server: the machine that you want access to.</p>
</li>
<li><p>The client: The system that you are accessing the server from.</p>
</li>
</ul>
<p>Connection to a server follows these steps:</p>
<ol>
<li><p>Initiate Connection: The client sends a connection request to the server.</p>
</li>
<li><p>Exchange of Keys: The server sends its public key to the client. Both agree on the encryption methods to use.</p>
</li>
<li><p>Session Key Generation: The client and server use the Diffie-Hellman key exchange to create a shared session key.</p>
</li>
<li><p>Client Authentication: The client logs in to the server using a password, private key, or another method.</p>
</li>
<li><p>Secure Communication: After authentication, the client and server communicate securely with encryption.</p>
</li>
</ol>
<p><strong>How to connect to a remote server using SSH?</strong></p>
<p>The <code>ssh</code> command is a built-in utility in Linux and also the default one. It makes accessing servers quite easy and secure.</p>
<p>Here, we are talking about how the client would make a connection to the server.</p>
<p>Prior to connecting to a server, you need to have the following information:</p>
<ul>
<li><p>The IP address or the domain name of the server.</p>
</li>
<li><p>The username and password of the server.</p>
</li>
<li><p>The port number that you have access to in the server.</p>
</li>
</ul>
<p>The basic syntax of the <code>ssh</code> command is:</p>
<pre><code class="lang-bash">ssh username@server_ip
</code></pre>
<p>For example, if your username is <code>john</code> and the server IP is <code>192.168.1.10</code>, the command would be:</p>
<pre><code class="lang-bash">ssh john@192.168.1.10
</code></pre>
<p>After that, you'll be prompted to enter the secret password. Your screen will look similar to this:</p>
<pre><code class="lang-bash">john@192.168.1.10<span class="hljs-string">'s password: 
Welcome to Ubuntu 20.04.2 LTS (GNU/Linux 5.4.0-70-generic x86_64)

 * Documentation:  https://help.ubuntu.com
 * Management:     https://landscape.canonical.com
 * Support:        https://ubuntu.com/advantage

  System information as of Fri Jun  5 10:17:32 UTC 2024

  System load:  0.08               Processes:           122
  Usage of /:   12.3% of 19.56GB   Users logged in:     1
  Memory usage: 53%                IP address for eth0: 192.168.1.10
  Swap usage:   0%

Last login: Fri Jun  5 09:34:56 2024 from 192.168.1.2
john@hostname:~$ # start entering commands</span>
</code></pre>
<p>Now you can execute the relevant commands on the server <code>192.168.1.10</code>.</p>
<p>⚠️ The default port for ssh is <code>22</code> but it is also vulnerable, as hackers will likely attempt here first. Your server can expose another port and share the access with you. To connect to a different port, use the <code>-p</code> flag.</p>
<pre><code class="lang-bash">ssh -p port_number username@server_ip
</code></pre>
<h3 id="heading-83-advanced-log-parsing-and-analysis">8.3. Advanced Log Parsing and Analysis</h3>
<p>Log files, when configured, are generated by your system for a variety of useful reasons. They can be used to track system events, monitor system performance, and troubleshoot issues. They are specifically useful for system administrators where they can track application errors, network events, and user activity.</p>
<p>Here is an example of a log file:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># sample log file</span>
2024-04-25 09:00:00 INFO Startup: Application starting
2024-04-25 09:01:00 INFO Config: Configuration loaded successfully
2024-04-25 09:02:00 DEBUG Database: Database connection established
2024-04-25 09:03:00 INFO User: New user registered (UserID: 1001)
2024-04-25 09:04:00 WARN Security: Attempted login with incorrect credentials (UserID: 1001)
2024-04-25 09:05:00 ERROR Network: Network timeout on request (ReqID: 456)
2024-04-25 09:06:00 INFO Email: Notification email sent (UserID: 1001)
2024-04-25 09:07:00 DEBUG API: API call with response time over threshold (Duration: 350ms)
2024-04-25 09:08:00 INFO Session: User session ended (UserID: 1001)
2024-04-25 09:09:00 INFO Shutdown: Application shutdown initiated
</code></pre>
<p>A log file usually contains the following columns:</p>
<ul>
<li><p>Timestamp: The date and time when the event occurred.</p>
</li>
<li><p>Log Level: The severity of the event (INFO, DEBUG, WARN, ERROR).</p>
</li>
<li><p>Component: The component of the system that generated the event (Startup, Config, Database, User, Security, Network, Email, API, Session, Shutdown).</p>
</li>
<li><p>Message: A description of the event that occurred.</p>
</li>
<li><p>Additional Information: Additional information related to the event.</p>
</li>
</ul>
<p>In real-time systems, log files tend to be thousands of lines long and are generated every second. They can be very wordy depending on the configuration. Every column in a log file is a piece of information that can be used to track down issues. This makes log files difficult to read and understand manually.</p>
<p>This is where log parsing comes in. Log parsing is the process of extracting useful information from log files. It involves breaking down the log files into smaller, more manageable pieces, and extracting the relevant information.</p>
<p>The filtered information can also be useful for creating alerts, reports, and dashboards.</p>
<p>In this section, you will explore some techniques for parsing log files in Linux.</p>
<h4 id="heading-text-extraction-using-grep">Text extraction using <code>grep</code></h4>
<p>Grep is a built-in bash utility. It stands for "global regular expression print". Grep is used to match strings in files.</p>
<p>Here are some common uses of <code>grep</code>:</p>
<ol>
<li><p><strong>Search for a specific string in a file:</strong></p>
<pre><code class="lang-bash"> grep <span class="hljs-string">"search_string"</span> filename
</code></pre>
<p> This command searches for "search_string" in the file named <code>filename</code>.</p>
</li>
<li><p><strong>Search recursively in directories:</strong></p>
<pre><code class="lang-bash"> grep -r <span class="hljs-string">"search_string"</span> /path/to/directory
</code></pre>
<p> This command searches for "<code>search_string"</code> in all files within the specified directory and its subdirectories.</p>
</li>
<li><p><strong>Ignore case while searching:</strong></p>
<pre><code class="lang-bash"> grep -i <span class="hljs-string">"search_string"</span> filename
</code></pre>
<p> This command performs a case-insensitive search for "search_string" in the file named <code>filename</code>.</p>
</li>
<li><p><strong>Display line numbers with matching lines:</strong></p>
<pre><code class="lang-bash"> grep -n <span class="hljs-string">"search_string"</span> filename
</code></pre>
<p> This command shows the line numbers along with the matching lines in the file named <code>filename</code>.</p>
</li>
<li><p><strong>Count the number of matching lines:</strong></p>
<pre><code class="lang-bash"> grep -c <span class="hljs-string">"search_string"</span> filename
</code></pre>
<p> This command counts the number of lines that contain "search_string" in the file named <code>filename</code>.</p>
</li>
<li><p><strong>Invert match to display lines that do not match:</strong></p>
<pre><code class="lang-bash"> grep -v <span class="hljs-string">"search_string"</span> filename
</code></pre>
<p> This command displays all lines that do not contain "search_string" in the file named <code>filename</code>.</p>
</li>
<li><p><strong>Search for a whole word:</strong></p>
<pre><code class="lang-bash"> grep -w <span class="hljs-string">"word"</span> filename
</code></pre>
<p> This command searches for the whole word "word" in the file named <code>filename</code>.</p>
</li>
<li><p><strong>Use extended regular expressions:</strong></p>
<pre><code class="lang-bash"> grep -E <span class="hljs-string">"pattern"</span> filename
</code></pre>
<p> This command allows the use of extended regular expressions for more complex pattern matching in the file named <code>filename</code>.</p>
</li>
</ol>
<p><strong>💡 Tip:</strong> If there are multiple files in a folder, you can use the below command to find the list of files containing the desired strings.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># find the list of files containing the desired strings</span>
grep -l <span class="hljs-string">"String to Match"</span> /path/to/directory
</code></pre>
<h4 id="heading-text-extraction-using-sed">Text extraction using <code>sed</code></h4>
<p><code>sed</code> stands for "stream editor". It processes data stream-wise, meaning it reads data one line at a time. <code>sed</code> allows you to search for patterns and perform actions on the lines that match those patterns.</p>
<p><strong>Basic syntax of</strong><code>sed</code>:</p>
<p>The basic syntax of <code>sed</code> is as follows:</p>
<pre><code class="lang-bash">sed [options] <span class="hljs-string">'command'</span> file_name
</code></pre>
<p>Here, <code>command</code> is used to perform operations like substitution, deletion, insertion, and so on, on the text data. The filename is the name of the file you want to process.</p>
<p><code>sed</code><strong>usage:</strong></p>
<p><strong>1. Substitution:</strong></p>
<p>The <code>s</code> flag is used to replace text. The <code>old-text</code> is replaced with <code>new-text</code>:</p>
<pre><code class="lang-bash">sed <span class="hljs-string">'s/old-text/new-text/'</span> filename
</code></pre>
<p>For example, to change all instances of "error" to "warning" in the log file <code>system.log</code>:</p>
<pre><code class="lang-bash">sed <span class="hljs-string">'s/error/warning/'</span> system.log
</code></pre>
<p><strong>2. Printing lines containing a specific pattern:</strong></p>
<p>Using <code>sed</code> to filter and display lines that match a specific pattern:</p>
<pre><code class="lang-bash">sed -n <span class="hljs-string">'/pattern/p'</span> filename
</code></pre>
<p>For instance, to find all lines containing "ERROR":</p>
<pre><code class="lang-bash">sed -n <span class="hljs-string">'/ERROR/p'</span> system.log
</code></pre>
<p><strong>3. Deleting lines containing a specific pattern:</strong></p>
<p>You can delete lines from the output that match a specific pattern:</p>
<pre><code class="lang-bash">sed <span class="hljs-string">'/pattern/d'</span> filename
</code></pre>
<p>For example, to remove all lines containing "DEBUG":</p>
<pre><code class="lang-bash">sed <span class="hljs-string">'/DEBUG/d'</span> system.log
</code></pre>
<p><strong>4. Extracting specific fields from a log line:</strong></p>
<p>You can use regular expressions to extract parts of lines. Suppose each log line starts with a date in the format "YYYY-MM-DD". You could extract just the date from each line:</p>
<pre><code class="lang-bash">sed -n <span class="hljs-string">'s/^\([0-9]\{4\}-[0-9]\{2\}-[0-9]\{2\}\).*/\1/p'</span> system.log
</code></pre>
<h4 id="heading-text-parsing-with-awk">Text parsing with <code>awk</code></h4>
<p><code>awk</code> has the ability to easily split each line into fields. It's well-suited for processing structured text like log files.</p>
<p><strong>Basic syntax of</strong><code>awk</code></p>
<p>The basic syntax of <code>awk</code> is:</p>
<pre><code class="lang-bash">awk <span class="hljs-string">'pattern { action }'</span> file_name
</code></pre>
<p>Here, <code>pattern</code> is a condition that must be met for the <code>action</code> to be performed. If the pattern is omitted, the action is performed on every line.</p>
<p>In the coming examples, you'll use this log file as an example:</p>
<pre><code class="lang-bash">2024-04-25 09:00:00 INFO Startup: Application starting
2024-04-25 09:01:00 INFO Config: Configuration loaded successfully
2024-04-25 09:02:00 INFO Database: Database connection established
2024-04-25 09:03:00 INFO User: New user registered (UserID: 1001)
2024-04-25 09:04:00 INFO Security: Attempted login with incorrect credentials (UserID: 1001)
2024-04-25 09:05:00 INFO Network: Network timeout on request (ReqID: 456)
2024-04-25 09:06:00 INFO Email: Notification email sent (UserID: 1001)
2024-04-25 09:07:00 INFO API: API call with response time over threshold (Duration: 350ms)
2024-04-25 09:08:00 INFO Session: User session ended (UserID: 1001)
2024-04-25 09:09:00 INFO Shutdown: Application shutdown initiated
  INFO
</code></pre>
<ul>
<li><strong>Accessing columns using</strong><code>awk</code></li>
</ul>
<p>The fields in <code>awk</code> (separated by spaces by default) can be accessed using <code>$1</code>, <code>$2</code>, <code>$3</code>, and so on.</p>
<pre><code class="lang-bash">zaira@zaira-ThinkPad:~$ awk <span class="hljs-string">'{ print $1 }'</span> sample.log
<span class="hljs-comment"># output</span>
2024-04-25
2024-04-25
2024-04-25
2024-04-25
2024-04-25
2024-04-25
2024-04-25
2024-04-25
2024-04-25
2024-04-25

zaira@zaira-ThinkPad:~$ awk <span class="hljs-string">'{ print $2 }'</span> sample.log
<span class="hljs-comment"># output</span>
09:00:00
09:01:00
09:02:00
09:03:00
09:04:00
09:05:00
09:06:00
09:07:00
09:08:00
09:09:00
</code></pre>
<ul>
<li><strong>Print lines containing a specific pattern (for example, ERROR)</strong></li>
</ul>
<pre><code class="lang-bash">awk <span class="hljs-string">'/ERROR/ { print $0 }'</span> logfile.log

<span class="hljs-comment"># output</span>
2024-04-25 09:05:00 ERROR Network: Network timeout on request (ReqID: 456)
</code></pre>
<p>This prints all lines that contain "ERROR".</p>
<ul>
<li><strong>Extract the first field (Date and Time)</strong></li>
</ul>
<pre><code class="lang-bash">awk <span class="hljs-string">'{ print $1, $2 }'</span> logfile.log
<span class="hljs-comment"># output</span>
2024-04-25 09:00:00
2024-04-25 09:01:00
2024-04-25 09:02:00
2024-04-25 09:03:00
2024-04-25 09:04:00
2024-04-25 09:05:00
2024-04-25 09:06:00
2024-04-25 09:07:00
2024-04-25 09:08:007
2024-04-25 09:09:00
</code></pre>
<p>This will extract the first two fields from each line, which in this case would be the date and time.</p>
<ul>
<li><strong>Summarize occurrences of each log level</strong></li>
</ul>
<pre><code class="lang-bash">awk <span class="hljs-string">'{ count[$3]++ } END { for (level in count) print level, count[level] }'</span> logfile.log

<span class="hljs-comment"># output</span>
 1
WARN 1
ERROR 1
DEBUG 2
INFO 6
</code></pre>
<p>The output will be a summary of the number of occurrences of each log level.</p>
<ul>
<li><strong>Filter out specific fields (for example, where the 3rd field is INFO)</strong></li>
</ul>
<pre><code class="lang-bash">awk <span class="hljs-string">'{ $3="INFO"; print }'</span> sample.log

<span class="hljs-comment"># output</span>
2024-04-25 09:00:00 INFO Startup: Application starting
2024-04-25 09:01:00 INFO Config: Configuration loaded successfully
2024-04-25 09:02:00 INFO Database: Database connection established
2024-04-25 09:03:00 INFO User: New user registered (UserID: 1001)
2024-04-25 09:04:00 INFO Security: Attempted login with incorrect credentials (UserID: 1001)
2024-04-25 09:05:00 INFO Network: Network timeout on request (ReqID: 456)
2024-04-25 09:06:00 INFO Email: Notification email sent (UserID: 1001)
2024-04-25 09:07:00 INFO API: API call with response time over threshold (Duration: 350ms)
2024-04-25 09:08:00 INFO Session: User session ended (UserID: 1001)
2024-04-25 09:09:00 INFO Shutdown: Application shutdown initiated
  INFO
</code></pre>
<p>This command will extract all lines where the 3rd field is "INFO".</p>
<p>💡 <strong>Tip:</strong> The default separator in <code>awk</code> is a space. If your log file uses a different separator, you can specify it using the <code>-F</code> option. For example, if your log file uses a colon as a separator, you can use <code>awk -F: '{ print $1 }' logfile.log</code> to extract the first field.</p>
<h4 id="heading-parsing-log-files-with-cut">Parsing log files with <code>cut</code></h4>
<p>The <code>cut</code> command is a simple yet powerful command used to extract sections of text from each line of input. As log files are structured and each field is delimited by a specific character, such as a space, tab, or a custom delimiter, <code>cut</code> does a very good job of extracting those specific fields.</p>
<p>The basic syntax of the cut command is:</p>
<pre><code class="lang-bash">cut [options] [file]
</code></pre>
<p>Some commonly used options for the cut command:</p>
<ul>
<li><p><code>-d</code> : Specifies a delimiter used as the field separator.</p>
</li>
<li><p><code>-f</code> : Selects the fields to be displayed.</p>
</li>
<li><p><code>-c</code> : Specifies character positions.</p>
</li>
</ul>
<p>For example, the command below would extract the first field (separated by a space) from each line of the log file:</p>
<pre><code class="lang-bash">cut -d <span class="hljs-string">' '</span> -f 1 logfile.log
</code></pre>
<p><strong>Examples of using</strong><code>cut</code><strong>for log parsing</strong></p>
<p>Assume you have a log file structured as follows, where fields are space-separated:</p>
<pre><code class="lang-bash">2024-04-25 08:23:01 INFO 192.168.1.10 User logged <span class="hljs-keyword">in</span> successfully.
2024-04-25 08:24:15 WARNING 192.168.1.10 Disk usage exceeds 90%.
2024-04-25 08:25:02 ERROR 10.0.0.5 Connection timed out.
...
</code></pre>
<p><code>cut</code> can be used in the following ways:</p>
<ol>
<li><strong>Extracting the time from each log entry</strong>:</li>
</ol>
<pre><code class="lang-bash">cut -d <span class="hljs-string">' '</span> -f 2 system.log

<span class="hljs-comment"># Output</span>
08:23:01
08:24:15
08:25:02
...
</code></pre>
<p>This command uses a space as a delimiter and selects the second field, which is the time component of each log entry.</p>
<ol start="2">
<li><strong>Extracting the IP addresses from the logs</strong>:</li>
</ol>
<pre><code class="lang-bash">cut -d <span class="hljs-string">' '</span> -f 4 system.log

<span class="hljs-comment"># Output</span>
192.168.1.10
192.168.1.10
10.0.0.5
</code></pre>
<p>This command extracts the fourth field, which is the IP address from each log entry.</p>
<ol start="3">
<li><strong>Extracting log levels (INFO, WARNING, ERROR)</strong>:</li>
</ol>
<pre><code class="lang-bash">cut -d <span class="hljs-string">' '</span> -f 3 system.log

<span class="hljs-comment"># Output</span>
INFO
WARNING
ERROR
</code></pre>
<p>This extracts the third field which contains the log level.</p>
<ol start="4">
<li><strong>Combining</strong><code>cut</code><strong>with other commands:</strong></li>
</ol>
<p>The output of other commands can be piped to the <code>cut</code> command. Let's say you want to filter logs before cutting. You can use <code>grep</code> to extract lines containing "ERROR" and then use <code>cut</code> to get specific information from those lines:</p>
<pre><code class="lang-bash">grep <span class="hljs-string">"ERROR"</span> system.log | cut -d <span class="hljs-string">' '</span> -f 1,2 

<span class="hljs-comment"># Output</span>
2024-04-25 08:25:02
</code></pre>
<p>This command first filters lines that include "ERROR", then extracts the date and time from these lines.</p>
<ol start="5">
<li><strong>Extracting multiple fields</strong>:</li>
</ol>
<p>It is possible to extract multiple fields at once by specifying a range or a comma-separated list of fields:</p>
<pre><code class="lang-bash">cut -d <span class="hljs-string">' '</span> -f 1,2,3 system.log` 

<span class="hljs-comment"># Output</span>
2024-04-25 08:23:01 INFO
2024-04-25 08:24:15 WARNING
2024-04-25 08:25:02 ERROR
...
</code></pre>
<p>The above command extracts the first three fields from each log entry that are date, time, and log level.</p>
<h4 id="heading-parsing-log-files-with-sort-and-uniq">Parsing log files with <code>sort</code> and <code>uniq</code></h4>
<p>Sorting and removing duplicates are common operations when working with log files. The <code>sort</code> and <code>uniq</code> commands are powerful commands used to sort and remove duplicates from the input, respectively.</p>
<p><strong>Basic syntax of sort</strong></p>
<p>The <code>sort</code> command organizes lines of text alphabetically or numerically.</p>
<pre><code class="lang-bash">sort [options] [file]
</code></pre>
<p>Some key options for the sort command:</p>
<ul>
<li><p><code>-n</code>: Sorts the file assuming the contents are numerical.</p>
</li>
<li><p><code>-r</code>: Reverses the order of sort.</p>
</li>
<li><p><code>-k</code>: Specifies a key or column number to sort on.</p>
</li>
<li><p><code>-u</code>: Sorts and removes duplicate lines.</p>
</li>
</ul>
<p>The <code>uniq</code> command is used to filter or count and report repeated lines in a file.</p>
<p>The syntax of <code>uniq</code> is:</p>
<pre><code class="lang-bash">uniq [options] [input_file] [output_file]
</code></pre>
<p>Some key options for the <code>uniq</code> command are:</p>
<ul>
<li><p><code>-c</code>: Prefixes lines by the number of occurrences.</p>
</li>
<li><p><code>-d</code>: Only prints duplicate lines.</p>
</li>
<li><p><code>-u</code>: Only prints unique lines.</p>
</li>
</ul>
<h4 id="heading-examples-of-using-sort-and-uniq-together-for-log-parsing">Examples of using <code>sort</code> and <code>uniq</code> together for log parsing</h4>
<p>Let's assume the following example log entries for these demonstrations:</p>
<pre><code class="lang-bash">2024-04-25 INFO User logged <span class="hljs-keyword">in</span> successfully.
2024-04-25 WARNING Disk usage exceeds 90%.
2024-04-26 ERROR Connection timed out.
2024-04-25 INFO User logged <span class="hljs-keyword">in</span> successfully.
2024-04-26 INFO Scheduled maintenance.
2024-04-26 ERROR Connection timed out.
</code></pre>
<ol>
<li><strong>Sorting log entries by date</strong>:</li>
</ol>
<pre><code class="lang-bash">sort system.log

<span class="hljs-comment"># Output</span>
2024-04-25 INFO User logged <span class="hljs-keyword">in</span> successfully.
2024-04-25 INFO User logged <span class="hljs-keyword">in</span> successfully.
2024-04-25 WARNING Disk usage exceeds 90%.
2024-04-26 ERROR Connection timed out.
2024-04-26 ERROR Connection timed out.
2024-04-26 INFO Scheduled maintenance.
</code></pre>
<p>This sorts the log entries alphabetically, which effectively sorts them by date if the date is the first field.</p>
<ol>
<li><strong>Sorting and removing duplicates</strong>:</li>
</ol>
<pre><code class="lang-bash">sort system.log | uniq

<span class="hljs-comment"># Output</span>
2024-04-25 INFO User logged <span class="hljs-keyword">in</span> successfully.
2024-04-25 WARNING Disk usage exceeds 90%.
2024-04-26 ERROR Connection timed out.
2024-04-26 INFO Scheduled maintenance.
</code></pre>
<p>This command sorts the log file and pipes it to <code>uniq</code>, removing duplicate lines.</p>
<ol>
<li><strong>Counting occurrences of each line</strong>:</li>
</ol>
<pre><code class="lang-bash">sort system.log | uniq -c

<span class="hljs-comment"># Output</span>
2 2024-04-25 INFO User logged <span class="hljs-keyword">in</span> successfully.
1 2024-04-25 WARNING Disk usage exceeds 90%.
2 2024-04-26 ERROR Connection timed out.
1 2024-04-26 INFO Scheduled maintenance.
</code></pre>
<p>Sorts the log entries and then counts each unique line. According to the output, the line <code>'2024-04-25 INFO User logged in successfully.'</code> appeared 2 times in the file.</p>
<ol>
<li><strong>Identifying unique log entries</strong>:</li>
</ol>
<pre><code class="lang-bash">sort system.log | uniq -u

<span class="hljs-comment"># Output</span>

2024-04-25 WARNING Disk usage exceeds 90%.
2024-04-26 INFO Scheduled maintenance.
</code></pre>
<p>This command shows lines that are unique.</p>
<ol start="2">
<li><strong>Sorting by log level</strong>:</li>
</ol>
<pre><code class="lang-bash">sort -k2 system.log

<span class="hljs-comment"># Output</span>
2024-04-26 ERROR Connection timed out.
2024-04-26 ERROR Connection timed out.
2024-04-25 INFO User logged <span class="hljs-keyword">in</span> successfully.
2024-04-25 INFO User logged <span class="hljs-keyword">in</span> successfully.
2024-04-26 INFO Scheduled maintenance.
2024-04-25 WARNING Disk usage exceeds 90%.
</code></pre>
<p>Sorts the entries based on the second field, which is the log level.</p>
<h3 id="heading-84-managing-linux-processes-via-command-line">8.4. Managing Linux Processes via Command Line</h3>
<p>A process is a running instance of a program. A process consists of:</p>
<ul>
<li><p>An address space of the allocated memory.</p>
</li>
<li><p>Process states.</p>
</li>
<li><p>Properties such as ownership, security attributes, and resource usage.</p>
</li>
</ul>
<p>A process also has an environment that consists of:</p>
<ul>
<li><p>Local and global variables</p>
</li>
<li><p>The current scheduling context</p>
</li>
<li><p>Allocated system resources, such as network ports or file descriptors.</p>
</li>
</ul>
<p>When you run the <code>ls -l</code> command, the operating system creates a new process to execute the command. The process has an ID, a state, and runs until the command completes.</p>
<h4 id="heading-understanding-process-creation-and-lifecycle">Understanding process creation and lifecycle</h4>
<p>In Ubuntu, all processes originate from the initial system process called <code>systemd</code>, which is the first process started by the kernel during boot.</p>
<p>The <code>systemd</code> process has a process ID (PID) of <code>1</code> and is responsible for initializing the system, starting and managing other processes, and handling system services. All other processes on the system are descendants of <code>systemd</code>.</p>
<p>A parent process duplicates its own address space (fork) to create a new (child) process structure. Each new process is assigned a unique process ID (PID) for tracking and security purposes. The PID and the parent's process ID (PPID) are part of the new process environment. Any process can create a child process.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719584071059/f24fac4b-18f3-4a39-8659-93d32c533256.png" alt="Process and its initialization to parent and child" class="image--center mx-auto" width="473" height="649" loading="lazy"></p>
<p>Through the fork routine, a child process inherits security identities, previous and current file descriptors, port and resource privileges, environment variables, and program code. A child process may then execute its own program code.</p>
<p>Typically, a parent process sleeps while the child process runs, setting a request (wait) to be notified when the child completes.</p>
<p>Upon exiting, the child process has already closed or discarded its resources and environment. The only remaining resource, known as a zombie, is an entry in the process table. The parent, signaled awake when the child exits, cleans the process table of the child's entry, thus freeing the last resource of the child process. The parent process then continues executing its own program code.</p>
<h4 id="heading-understanding-process-states">Understanding process states</h4>
<p>Processes in Linux assume different states during their lifecycle. The state of a process indicates what the process is currently doing and how it is interacting with the system. The processes transition between states based on their execution status and the system's scheduling algorithm.</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1719584116150/3054dfe2-c42c-4d62-9e12-e3aec479d53a.png" alt="Linux process states and transitions" class="image--center mx-auto" width="1079" height="742" loading="lazy"></p>
<p>The processes in a Linux system can be in one of the following states:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>State</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>(new)</strong></td><td>Initial state when a process is created via a fork system call.</td></tr>
<tr>
<td><strong>Runnable (ready) (R)</strong></td><td>Process is ready to run and waiting to be scheduled on a CPU.</td></tr>
<tr>
<td><strong>Running (user) (R)</strong></td><td>Process is executing in user mode, running user applications.</td></tr>
<tr>
<td><strong>Running (kernel) (R)</strong></td><td>Process is executing in kernel mode, handling system calls or hardware interrupts.</td></tr>
<tr>
<td><strong>Sleeping (S)</strong></td><td>Process is waiting for an event (for example, I/O operation) to complete and can be easily awakened.</td></tr>
<tr>
<td><strong>Sleeping (uninterruptible) (D)</strong></td><td>Process is in an uninterruptible sleep state, waiting for a specific condition (usually I/O) to complete, and cannot be interrupted by signals.</td></tr>
<tr>
<td><strong>Sleeping (disk sleep) (K)</strong></td><td>Process is waiting for disk I/O operations to complete.</td></tr>
<tr>
<td><strong>Sleeping (idle) (I)</strong></td><td>Process is idle, not doing any work, and waiting for an event to occur.</td></tr>
<tr>
<td><strong>Stopped (T)</strong></td><td>Process execution has been stopped, typically by a signal, and can be resumed later.</td></tr>
<tr>
<td><strong>Zombie (Z)</strong></td><td>Process has completed execution but still has an entry in the process table, waiting for its parent to read its exit status.</td></tr>
</tbody>
</table>
</div><p>The processes transition between these states in the following ways:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>Transition</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td><strong>Fork</strong></td><td>Creates a new process from a parent process, transitioning from (new) to Runnable (ready) (R).</td></tr>
<tr>
<td><strong>Schedule</strong></td><td>Scheduler selects a runnable process, transitioning it to Running (user) or Running (kernel) state.</td></tr>
<tr>
<td><strong>Run</strong></td><td>Process transitions from Runnable (ready) (R) to Running (kernel) (R) when scheduled for execution.</td></tr>
<tr>
<td><strong>Preempt or Reschedule</strong></td><td>Process can be preempted or rescheduled, moving it back to Runnable (ready) (R) state.</td></tr>
<tr>
<td><strong>Syscall</strong></td><td>Process makes a system call, transitioning from Running (user) (R) to Running (kernel) (R).</td></tr>
<tr>
<td><strong>Return</strong></td><td>Process completes a system call and returns to Running (user) (R).</td></tr>
<tr>
<td><strong>Wait</strong></td><td>Process waits for an event, transitioning from Running (kernel) (R) to one of the Sleeping states (S, D, K, or I).</td></tr>
<tr>
<td><strong>Event or Signal</strong></td><td>Process is awakened by an event or signal, moving it from a Sleeping state back to Runnable (ready) (R).</td></tr>
<tr>
<td><strong>Suspend</strong></td><td>Process is suspended, transitioning from Running (kernel) or Runnable (ready) to Stopped (T).</td></tr>
<tr>
<td><strong>Resume</strong></td><td>Process is resumed, moving from Stopped (T) back to Runnable (ready) (R).</td></tr>
<tr>
<td><strong>Exit</strong></td><td>Process terminates, transitioning from Running (user) or Running (kernel) to Zombie (Z).</td></tr>
<tr>
<td><strong>Reap</strong></td><td>Parent process reads the exit status of the zombie process, removing it from the process table.</td></tr>
</tbody>
</table>
</div><h4 id="heading-how-to-view-processes">How to view processes</h4>
<p>You can use the <code>ps</code> command along with a combination of options to view processes on a Linux system. The <code>ps</code> command is used to display information about a selection of active processes. For example, <code>ps aux</code> displays all processes running on the system.</p>
<pre><code class="lang-bash">zaira@zaira:~$ ps aux
<span class="hljs-comment"># Output</span>
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
root           1  0.0  0.0 168140 11352 ?        Ss   May21   0:18 /sbin/init splash
root           2  0.0  0.0      0     0 ?        S    May21   0:00 [kthreadd]
root           3  0.0  0.0      0     0 ?        I&lt;   May21   0:00 [rcu_gp]
root           4  0.0  0.0      0     0 ?        I&lt;   May21   0:00 [rcu_par_gp]
root           5  0.0  0.0      0     0 ?        I&lt;   May21   0:00 [slub_flushwq]
root           6  0.0  0.0      0     0 ?        I&lt;   May21   0:00 [netns]
root          11  0.0  0.0      0     0 ?        I&lt;   May21   0:00 [mm_percpu_wq]
root          12  0.0  0.0      0     0 ?        I    May21   0:00 [rcu_tasks_kthread]
root          13  0.0  0.0      0     0 ?        I    May21   0:00 [rcu_tasks_rude_kthread]
*... output truncated ....*
</code></pre>
<p>The output above shows a snapshot of the currently running processes on the system. Each row represents a process with the following columns:</p>
<ol>
<li><p><code>USER</code>: The user who owns the process.</p>
</li>
<li><p><code>PID</code>: The process ID.</p>
</li>
<li><p><code>%CPU</code>: The CPU usage of the process.</p>
</li>
<li><p><code>%MEM</code>: The memory usage of the process.</p>
</li>
<li><p><code>VSZ</code>: The virtual memory size of the process.</p>
</li>
<li><p><code>RSS</code>: The resident set size, that is the non-swapped physical memory that a task has used.</p>
</li>
<li><p><code>TTY</code>: The controlling terminal of the process. A <code>?</code> indicates no controlling terminal.</p>
</li>
<li><p><code>STAT</code>: The process state.</p>
<ul>
<li><p><code>R</code>: Running</p>
</li>
<li><p><code>I</code> or <code>S</code>: Interruptible sleep (waiting for an event to complete)</p>
</li>
<li><p><code>D</code>: Uninterruptible sleep (usually IO)</p>
</li>
<li><p><code>T</code>: Stopped (either by a job control signal or because it is being traced)</p>
</li>
<li><p><code>Z</code>: Zombie (terminated but not reaped by its parent)</p>
</li>
<li><p><code>Ss</code>: Session leader. This is a process that has started a session, and it is a leader of a group of processes and can control terminal signals. The first <code>S</code> indicates the sleeping state, and the second <code>s</code> indicates it is a session leader.</p>
</li>
</ul>
</li>
<li><p><code>START</code>: The starting time or date of the process.</p>
</li>
<li><p><code>TIME</code>: The cumulative CPU time.</p>
</li>
<li><p><code>COMMAND</code>: The command that started the process.</p>
</li>
</ol>
<h4 id="heading-background-and-foreground-processes">Background and foreground processes</h4>
<p>In this section, you'll learn how you can control jobs by running them in the background or foreground.</p>
<p>A job is a process that is started by a shell. When you run a command in the terminal, it is considered a job. A job can run in the foreground or the background.</p>
<p>To demonstrate control, you'll first create 3 processes and then run them in the background. After that, you'll list the processes and alternate them between the foreground and background. You'll see how to put them to sleep or exit completely.</p>
<ol>
<li>Create Three Processes</li>
</ol>
<p>Open a terminal and start three long-running processes. Use the <code>sleep</code> command, that keeps the process running for a specified number of seconds.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># run sleep command for 300, 400, and 500 seconds</span>
sleep 300 &amp;
sleep 400 &amp;
sleep 500 &amp;
</code></pre>
<p>The <code>&amp;</code> at the end of each command moves the process to the background.</p>
<ol start="2">
<li>Display Background Jobs</li>
</ol>
<p>Use the <code>jobs</code> command to display the list of background jobs.</p>
<pre><code class="lang-bash"><span class="hljs-built_in">jobs</span>
</code></pre>
<p>The output should look something like this:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">jobs</span>
[1]   Running                 sleep 300 &amp;
[2]-  Running                 sleep 400 &amp;
[3]+  Running                 sleep 500 &amp;
</code></pre>
<ol start="3">
<li>Bring a Background Job to the Foreground</li>
</ol>
<p>To bring a background job to the foreground, use the <code>fg</code> command followed by the job number. For example, to bring the first job (<code>sleep 300</code>) to the foreground:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">fg</span> %1
</code></pre>
<p>This will bring job <code>1</code> to the foreground.</p>
<ol start="4">
<li>Move the Foreground Job Back to the Background</li>
</ol>
<p>While the job is running in the foreground, you can suspend it and move it back to the background by pressing <code>Ctrl+Z</code> to suspend the job.</p>
<p>A suspended job will look like this:</p>
<pre><code class="lang-bash">zaira@zaira:~$ <span class="hljs-built_in">fg</span> %1
sleep 300

^Z
[1]+  Stopped                 sleep 300

zaira@zaira:~$ <span class="hljs-built_in">jobs</span>
<span class="hljs-comment"># suspended job </span>
[1]+  Stopped                 sleep 300
[2]   Running                 sleep 400 &amp;
[3]-  Running                 sleep 500 &amp;
</code></pre>
<p>Now use the <code>bg</code> command to resume the job with ID 1 in the background.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Press Ctrl+Z to suspend the foreground job</span>
<span class="hljs-comment"># Then, resume it in the background</span>
<span class="hljs-built_in">bg</span> %1
</code></pre>
<ol start="5">
<li>Display the jobs again</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-built_in">jobs</span>
[1]   Running                 sleep 300 &amp;
[2]-  Running                 sleep 400 &amp;
[3]+  Running                 sleep 500 &amp;
</code></pre>
<p>In this exercise, you:</p>
<ul>
<li><p>Started three background processes using sleep commands.</p>
</li>
<li><p>Used jobs to display the list of background jobs.</p>
</li>
<li><p>Brought a job to the foreground with <code>fg %job_number</code>.</p>
</li>
<li><p>Suspended the job with <code>Ctrl+Z</code> and moved it back to the background with <code>bg %job_number</code>.</p>
</li>
<li><p>Used jobs again to verify the status of the background jobs.</p>
</li>
</ul>
<p>Now you know how to control jobs.</p>
<h4 id="heading-killing-processes">Killing processes</h4>
<p>It is possible to terminate an unresponsive or unwanted process using the <code>kill</code> command. The <code>kill</code> command sends a signal to a process ID, asking it to terminate.</p>
<p>A number of options are available with the <code>kill</code> command.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Options available with kill</span>

<span class="hljs-built_in">kill</span> -l
 1) SIGHUP     2) SIGINT     3) SIGQUIT     4) SIGILL     5) SIGTRAP
 6) SIGABRT     7) SIGBUS     8) SIGFPE     9) SIGKILL    10) SIGUSR1
11) SIGSEGV    12) SIGUSR2    13) SIGPIPE    14) SIGALRM    15) SIGTERM
16) SIGSTKFLT    17) SIGCHLD    18) SIGCONT    19) SIGSTOP    20) SIGTSTP
21) SIGTTIN    22) SIGTTOU    23) SIGURG    24) 
...terminated
</code></pre>
<p>Here are some examples of the <code>kill</code> command in Linux:</p>
<ol>
<li><p><strong>Kill a process by PID (Process ID):</strong></p>
<pre><code class="lang-bash"> <span class="hljs-built_in">kill</span> 1234
</code></pre>
<p> This command sends the default <code>SIGTERM</code> signal to the process with PID 1234, requesting it to terminate.</p>
</li>
<li><p><strong>Kill a process by name:</strong></p>
<pre><code class="lang-bash"> pkill process_name
</code></pre>
<p> This command sends the default <code>SIGTERM</code> signal to all processes with the specified name.</p>
</li>
<li><p><strong>Forcefully kill a process:</strong></p>
<pre><code class="lang-bash"> <span class="hljs-built_in">kill</span> -9 1234
</code></pre>
<p> This command sends the <code>SIGKILL</code> signal to the process with PID 1234, forcefully terminating it.</p>
</li>
<li><p><strong>Send a specific signal to a process:</strong></p>
<pre><code class="lang-bash"> <span class="hljs-built_in">kill</span> -s SIGSTOP 1234
</code></pre>
<p> This command sends the <code>SIGSTOP</code> signal to the process with PID 1234, stopping it.</p>
</li>
<li><p><strong>Kill all processes owned by a specific user:</strong></p>
<pre><code class="lang-bash"> pkill -u username
</code></pre>
<p> This command sends the default <code>SIGTERM</code> signal to all processes owned by the specified user.</p>
</li>
</ol>
<p>These examples demonstrate various ways to use the <code>kill</code> command to manage processes in a Linux environment.</p>
<p>Here is the information about the <code>kill</code> command options and signals in a tabular form: This table summarizes the most common <code>kill</code> command options and signals used in Linux for managing processes.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td>Command / Option</td><td>Signal</td><td>Description</td></tr>
</thead>
<tbody>
<tr>
<td><code>kill &lt;pid&gt;</code></td><td><code>SIGTERM</code></td><td>Requests the process to terminate gracefully (default signal).</td></tr>
<tr>
<td><code>kill -9 &lt;pid&gt;</code></td><td><code>SIGKILL</code></td><td>Forces the process to terminate immediately without cleanup.</td></tr>
<tr>
<td><code>kill -SIGKILL &lt;pid&gt;</code></td><td><code>SIGKILL</code></td><td>Forces the process to terminate immediately without cleanup.</td></tr>
<tr>
<td><code>kill -15 &lt;pid&gt;</code></td><td><code>SIGTERM</code></td><td>Explicitly sends the <code>SIGTERM</code> signal to request graceful termination.</td></tr>
<tr>
<td><code>kill -SIGTERM &lt;pid&gt;</code></td><td><code>SIGTERM</code></td><td>Explicitly sends the <code>SIGTERM</code> signal to request graceful termination.</td></tr>
<tr>
<td><code>kill -1 &lt;pid&gt;</code></td><td><code>SIGHUP</code></td><td>Traditionally means "hang up"; can be used to reload configuration files.</td></tr>
<tr>
<td><code>kill -SIGHUP &lt;pid&gt;</code></td><td><code>SIGHUP</code></td><td>Traditionally means "hang up"; can be used to reload configuration files.</td></tr>
<tr>
<td><code>kill -2 &lt;pid&gt;</code></td><td><code>SIGINT</code></td><td>Requests the process to terminate (same as pressing <code>Ctrl+C</code> in terminal).</td></tr>
<tr>
<td><code>kill -SIGINT &lt;pid&gt;</code></td><td><code>SIGINT</code></td><td>Requests the process to terminate (same as pressing <code>Ctrl+C</code> in terminal).</td></tr>
<tr>
<td><code>kill -3 &lt;pid&gt;</code></td><td><code>SIGQUIT</code></td><td>Causes the process to terminate and produce a core dump for debugging.</td></tr>
<tr>
<td><code>kill -SIGQUIT &lt;pid&gt;</code></td><td><code>SIGQUIT</code></td><td>Causes the process to terminate and produce a core dump for debugging.</td></tr>
<tr>
<td><code>kill -19 &lt;pid&gt;</code></td><td><code>SIGSTOP</code></td><td>Pauses the process.</td></tr>
<tr>
<td><code>kill -SIGSTOP &lt;pid&gt;</code></td><td><code>SIGSTOP</code></td><td>Pauses the process.</td></tr>
<tr>
<td><code>kill -18 &lt;pid&gt;</code></td><td><code>SIGCONT</code></td><td>Resumes a paused process.</td></tr>
<tr>
<td><code>kill -SIGCONT &lt;pid&gt;</code></td><td><code>SIGCONT</code></td><td>Resumes a paused process.</td></tr>
<tr>
<td><code>killall &lt;name&gt;</code></td><td>Varies</td><td>Sends a signal to all processes with the given name.</td></tr>
<tr>
<td><code>killall -9 &lt;name&gt;</code></td><td><code>SIGKILL</code></td><td>Force kills all processes with the given name.</td></tr>
<tr>
<td><code>pkill &lt;pattern&gt;</code></td><td>Varies</td><td>Sends a signal to processes based on a pattern match.</td></tr>
<tr>
<td><code>pkill -9 &lt;pattern&gt;</code></td><td><code>SIGKILL</code></td><td>Force kills all processes matching the pattern.</td></tr>
<tr>
<td><code>xkill</code></td><td><code>SIGKILL</code></td><td>Graphical utility that allows clicking on a window to kill the corresponding process.</td></tr>
</tbody>
</table>
</div><h3 id="heading-85-standard-input-and-output-streams-in-linux">8.5. Standard Input and Output Streams in Linux</h3>
<p>Reading an input and writing an output is an essential part of understanding the command line and shell scripting. In Linux, every process has three default streams:</p>
<ol>
<li><p>Standard Input (<code>stdin</code>): This stream is used for input, typically from the keyboard. When a program reads from <code>stdin</code>, it receives data entered by the user or redirected from a file. A file descriptor is a unique identifier that the operating system assigns to an open file in order to keep track of open files.</p>
<p> The file descriptor for <code>stdin</code> is <code>0</code>.</p>
</li>
<li><p>Standard Output (<code>stdout</code>): This is the default output stream where a process writes its output. By default, the standard output is the terminal. The output can also be redirected to a file or another program. The file descriptor for <code>stdout</code> is <code>1</code>.</p>
</li>
<li><p>Standard Error (<code>stderr</code>): This is the default error stream where a process writes its error messages. By default, the standard error is the terminal, allowing error messages to be seen even if <code>stdout</code> is redirected. The file descriptor for <code>stderr</code> is <code>2</code>.</p>
</li>
</ol>
<h4 id="heading-redirection-and-pipelines">Redirection and Pipelines</h4>
<p><strong>Redirection:</strong> You can redirect the error and output streams to files or other commands. For example:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Redirecting stdout to a file</span>
ls &gt; output.txt

<span class="hljs-comment"># Redirecting stderr to a file</span>
ls non_existent_directory 2&gt; error.txt

<span class="hljs-comment"># Redirecting both stdout and stderr to a file</span>
ls non_existent_directory &gt; all_output.txt 2&gt;&amp;1
</code></pre>
<p>In the last command,</p>
<ul>
<li><p><code>ls non_existent_directory</code>: lists the contents of a directory named non_existent_directory. Since this directory does not exist, <code>ls</code> will generate an error message.</p>
</li>
<li><p><code>&gt; all_output.txt</code>: The <code>&gt;</code> operator redirects the standard output (<code>stdout</code>) of the <code>ls</code> command to the file <code>all_output.txt</code>. If the file does not exist, it will be created. If it does exist, its contents will be overwritten.</p>
</li>
<li><p><code>2&gt;&amp;1:</code>: Here, <code>2</code> represents the file descriptor for standard error (<code>stderr</code>). <code>&amp;1</code> represents the file descriptor for standard output (<code>stdout</code>). The <code>&amp;</code> character is used to specify that <code>1</code> is not the file name but a file descriptor.</p>
</li>
</ul>
<p>So, <code>2&gt;&amp;1</code> means "redirect stderr (2) to wherever stdout (1) is currently going," which in this case is the file <code>all_output.txt</code>. Therefore, both the output (if there were any) and the error message from <code>ls</code> will be written to <code>all_output.txt</code>.</p>
<p><strong>Pipelines:</strong></p>
<p>You can use pipes (<code>|</code>) to pass the output of one command as the input to another:</p>
<pre><code class="lang-bash">ls | grep image
<span class="hljs-comment"># Output</span>
image-10.png
image-11.png
image-12.png
image-13.png
... Output truncated ...
</code></pre>
<h3 id="heading-86-automation-in-linux-automate-tasks-with-cron-jobs">8.6 Automation in Linux – Automate Tasks with Cron Jobs</h3>
<p>Cron is a powerful utility for job scheduling that is available in Unix-like operating systems. By configuring cron, you can set up automated jobs to run on a daily, weekly, monthly, or other specific time basis. The automation capabilities provided by cron play a crucial role in Linux system administration.</p>
<p>The <code>crond</code> daemon (a type of computer program that runs in the background) enables cron functionality. The cron reads the <strong>crontab</strong> (cron tables) for running predefined scripts.</p>
<p>By using a specific syntax, you can configure a cron job to schedule scripts or other commands to run automatically.</p>
<p><strong>What are cron jobs in Linux?</strong></p>
<p>Any task that you schedule through crons is called a cron job.</p>
<p>Now, let's see how cron jobs work.</p>
<h4 id="heading-how-to-control-access-to-crons">How to control access to crons</h4>
<p>In order to use cron jobs, an admin needs to allow cron jobs to be added for users in the <code>/etc/cron.allow</code> file.</p>
<p>If you get a prompt like this, it means you don't have permission to use cron.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/image-51.png" alt="Cron job addition denied for user John." width="600" height="400" loading="lazy"></p>
<p>To allow John to use crons, include his name in <code>/etc/cron.allow</code>. Create the file if it doesn't exist. This will allow John to create and edit cron jobs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2021/11/image-52.png" alt="Allowing John in file cron.allow" width="600" height="400" loading="lazy"></p>
<p>Users can also be denied access to cron job access by entering their usernames in the file <code>/etc/cron.d/cron.deny</code>.</p>
<h4 id="heading-how-to-add-cron-jobs-in-linux">How to add cron jobs in Linux</h4>
<p>First, to use cron jobs, you'll need to check the status of the cron service. If cron is not installed, you can easily download it through the package manager. Just use this to check:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Check cron service on Linux system</span>
sudo systemctl status cron.service
</code></pre>
<h4 id="heading-cron-job-syntax">Cron job syntax</h4>
<p>Crontabs use the following flags for adding and listing cron jobs:</p>
<ul>
<li><p><code>crontab -e</code>: edits crontab entries to add, delete, or edit cron jobs.</p>
</li>
<li><p><code>crontab -l</code>: list all the cron jobs for the current user.</p>
</li>
<li><p><code>crontab -u username -l</code>: list another user's crons.</p>
</li>
<li><p><code>crontab -u username -e</code>: edit another user's crons.</p>
</li>
</ul>
<p>When you list crons and they exist, you'll see something like this:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Cron job example</span>
* * * * * sh /path/to/script.sh
</code></pre>
<p>In the above example,</p>
<ul>
<li><code>*</code> represents minute(s) hour(s) day(s) month(s) weekday(s), respectively. See details of these values below:</li>
</ul>
<div class="hn-table">
<table>
<thead>
<tr>
<td></td><td><strong>VALUE</strong></td><td><strong>DESCRIPTION</strong></td></tr>
</thead>
<tbody>
<tr>
<td>Minutes</td><td>0-59</td><td>Command will be executed at the specific minute.</td></tr>
<tr>
<td>Hours</td><td>0-23</td><td>Command will be executed at the specific hour.</td></tr>
<tr>
<td>Days</td><td>1-31</td><td>Commands will be executed in these days of the months.</td></tr>
<tr>
<td>Months</td><td>1-12</td><td>The month in which tasks need to be executed.</td></tr>
<tr>
<td>Weekdays</td><td>0-6</td><td>Days of the week where commands will run. Here, 0 is Sunday.</td></tr>
</tbody>
</table>
</div><ul>
<li><p><code>sh</code> represents that the script is a bash script and should be run from <code>/bin/bash</code>.</p>
</li>
<li><p><code>/path/to/script.sh</code> specifies the path to the script.</p>
</li>
</ul>
<p>Below is a summary of the cron job syntax:</p>
<pre><code class="lang-markdown"><span class="hljs-bullet">*</span>   <span class="hljs-emphasis">*   *</span>   <span class="hljs-emphasis">*   *</span>  sh /path/to/script/script.sh
|   |   |   |   |              |
|   |   |   |   |      Command or Script to Execute        
|   |   |   |   |
|   |   |   |   |
|   |   |   |   |
|   |   |   | Day of the Week(0-6)
|   |   |   |
|   |   | Month of the Year(1-12)
|   |   |
|   | Day of the Month(1-31)  
|   |
| Hour(0-23)  
|
Min(0-59)
</code></pre>
<h4 id="heading-cron-job-examples">Cron job examples</h4>
<p>Below are some examples of scheduling cron jobs.</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>SCHEDULE</strong></td><td><strong>SCHEDULED VALUE</strong></td></tr>
</thead>
<tbody>
<tr>
<td><code>5 0 * 8 *</code></td><td>At 00:05 in August.</td></tr>
<tr>
<td><code>5 4 * * 6</code></td><td>At 04:05 on Saturday.</td></tr>
<tr>
<td><code>0 22 * * 1-5</code></td><td>At 22:00 on every day-of-week from Monday through Friday.</td></tr>
</tbody>
</table>
</div><p>It's okay if you are unable to grasp this all at once. You can practice and generate cron schedules with the <a target="_blank" href="https://crontab.guru/">crontab guru</a> website.</p>
<h4 id="heading-how-to-set-up-a-cron-job">How to set up a cron job</h4>
<p>In this section, we will look at an example of how to schedule a simple script with a cron job.</p>
<ol>
<li>Create a script called <code>date-script.sh</code> which prints the system date and time and appends it to a file. The script is shown below:</li>
</ol>
<pre><code class="lang-bash"><span class="hljs-meta">#!/bin/bash</span>

<span class="hljs-built_in">echo</span> `date` &gt;&gt; date-out.txt
</code></pre>
<p>2.  Make the script executable by giving it execution rights.</p>
<pre><code class="lang-bash">chmod 775 date-script.sh
</code></pre>
<p>3.  Add the script in the crontab using <code>crontab -e</code>.</p>
<p>Here, we have scheduled it to run per minute.</p>
<pre><code class="lang-bash">*/1 * * * * /bin/sh /root/date-script.sh
</code></pre>
<p>4.  Check the output of the file <code>date-out.txt</code>. According to the script, the system date should be printed to this file every minute.</p>
<pre><code class="lang-bash">cat date-out.txt
<span class="hljs-comment"># output</span>
Wed 26 Jun 16:59:33 PKT 2024
Wed 26 Jun 17:00:01 PKT 2024
Wed 26 Jun 17:01:01 PKT 2024
Wed 26 Jun 17:02:01 PKT 2024
Wed 26 Jun 17:03:01 PKT 2024
Wed 26 Jun 17:04:01 PKT 2024
Wed 26 Jun 17:05:01 PKT 2024
Wed 26 Jun 17:06:01 PKT 2024
Wed 26 Jun 17:07:01 PKT 2024
</code></pre>
<p><strong>How to troubleshoot crons</strong></p>
<p>Crons are really helpful, but they might not always work as intended. Fortunately, there are some effective methods you can use to troubleshoot them.</p>
<p><strong>1. Check the schedule.</strong></p>
<p>First, you can try verifying the schedule that's set for the cron. You can do that with the syntax you saw in the above sections.</p>
<p><strong>2</strong>. <strong>Check cron logs.</strong></p>
<p>First, you need to check if the cron has run at the intended time or not. In Ubuntu, you can verify this from the cron logs located at <code>/var/log/syslog</code>.</p>
<p>If there is an entry in these logs at the correct time, it means the cron has run according to the schedule you set.</p>
<p>Below are the logs of our cron job example. Note the first column which shows the timestamp. The path of the script is also mentioned at the end of the line. Line #1, 3, and 5 show that the script ran as intended.</p>
<pre><code class="lang-bash">1 Jun 26 17:02:01 zaira-ThinkPad CRON[27834]: (zaira) CMD (/bin/sh /home/zaira/date-script.sh)
2 Jun 26 17:02:02 zaira-ThinkPad systemd[2094]: Started Tracker metadata extractor.
3 Jun 26 17:03:01 zaira-ThinkPad CRON[28255]: (zaira) CMD (/bin/sh /home/zaira/date-script.sh)
4 Jun 26 17:03:02 zaira-ThinkPad systemd[2094]: Started Tracker metadata extractor.
5 Jun 26 17:04:01 zaira-ThinkPad CRON[28538]: (zaira) CMD (/bin/sh /home/zaira/date-script.sh)
</code></pre>
<p><strong>3. Redirect cron output to a file.</strong></p>
<p>You can redirect a cron's output to a file and check the file for any possible errors.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># Redirect cron output to a file</span>
* * * * * sh /path/to/script.sh &amp;&gt; log_file.log
</code></pre>
<h3 id="heading-87-linux-networking-basics">8.7. Linux Networking Basics</h3>
<p>Linux offers a number of commands to view network related information. In this section we will briefly discuss some of the commands.</p>
<h4 id="heading-view-network-interfaces-with-ifconfig">View network interfaces with <code>ifconfig</code></h4>
<p>The <code>ifconfig</code> command gives information about network interfaces. Here is an example output:</p>
<pre><code class="lang-bash">ifconfig

<span class="hljs-comment"># Output</span>
eth0: flags=4163&lt;UP,BROADCAST,RUNNING,MULTICAST&gt;  mtu 1500
        inet 192.168.1.100  netmask 255.255.255.0  broadcast 192.168.1.255
        inet6 fe80::a00:27ff:fe4e:66a1  prefixlen 64  scopeid 0x20&lt;link&gt;
        ether 08:00:27:4e:66:a1  txqueuelen 1000  (Ethernet)
        RX packets 1024  bytes 654321 (654.3 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 512  bytes 123456 (123.4 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0

lo: flags=73&lt;UP,LOOPBACK,RUNNING&gt;  mtu 65536
        inet 127.0.0.1  netmask 255.0.0.0
        inet6 ::1  prefixlen 128  scopeid 0x10&lt;host&gt;
        loop  txqueuelen 1000  (Local Loopback)
        RX packets 256  bytes 20480 (20.4 KB)
        RX errors 0  dropped 0  overruns 0  frame 0
        TX packets 256  bytes 20480 (20.4 KB)
        TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
</code></pre>
<p>The output of the <code>ifconfig</code> command shows the network interfaces configured on the system, along with details such as IP addresses, MAC addresses, packet statistics, and more.</p>
<p>These interfaces can be physical or virtual devices.</p>
<p>To extract IPv4 and IPv6 addresses, you can use <code>ip -4 addr</code> and <code>ip -6 addr</code>, respectively.</p>
<p><strong>View network activity with</strong><code>netstat</code></p>
<p>The <code>netstat</code> command shows network activity and stats by giving the following information:</p>
<p>Here are some examples of using the <code>netstat</code> command in the command line:</p>
<ol>
<li><p><strong>Display all listening and non-listening sockets:</strong></p>
<pre><code class="lang-bash"> netstat -a
</code></pre>
</li>
<li><p><strong>Show only listening ports:</strong></p>
<pre><code class="lang-bash"> netstat -l
</code></pre>
</li>
<li><p><strong>Display network statistics:</strong></p>
<pre><code class="lang-bash"> netstat -s
</code></pre>
</li>
<li><p><strong>Show routing table:</strong></p>
<pre><code class="lang-bash"> netstat -r
</code></pre>
</li>
<li><p><strong>Display TCP connections:</strong></p>
<pre><code class="lang-bash"> netstat -t
</code></pre>
</li>
<li><p><strong>Display UDP connections:</strong></p>
<pre><code class="lang-bash"> netstat -u
</code></pre>
</li>
<li><p><strong>Show network interfaces:</strong></p>
<pre><code class="lang-bash"> netstat -i
</code></pre>
</li>
<li><p><strong>Display PID and program names for connections:</strong></p>
<pre><code class="lang-bash"> netstat -p
</code></pre>
</li>
<li><p><strong>Show statistics for a specific protocol (for example, TCP):</strong></p>
<pre><code class="lang-bash"> netstat -st
</code></pre>
</li>
<li><p><strong>Display extended information:</strong></p>
<pre><code class="lang-bash">netstat -e
</code></pre>
</li>
</ol>
<h4 id="heading-check-network-connectivity-between-two-devices-using-ping">Check network connectivity between two devices using <code>ping</code></h4>
<p><code>ping</code> is used to test network connectivity between two devices. It sends ICMP packets to the target device and waits for a response.</p>
<pre><code class="lang-bash">ping google.com
</code></pre>
<p><code>ping</code> tests if you get a response back without getting a timeout.</p>
<pre><code class="lang-bash">ping google.com
PING google.com (142.250.181.46) 56(84) bytes of data.
64 bytes from fjr04s06-in-f14.1e100.net (142.250.181.46): icmp_seq=1 ttl=60 time=78.3 ms
64 bytes from fjr04s06-in-f14.1e100.net (142.250.181.46): icmp_seq=2 ttl=60 time=141 ms
64 bytes from fjr04s06-in-f14.1e100.net (142.250.181.46): icmp_seq=3 ttl=60 time=205 ms
64 bytes from fjr04s06-in-f14.1e100.net (142.250.181.46): icmp_seq=4 ttl=60 time=100 ms
^C
--- google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3001ms
rtt min/avg/max/mdev = 78.308/131.053/204.783/48.152 ms
</code></pre>
<p>You can stop the response with <code>Ctrl + C</code>.</p>
<h4 id="heading-testing-endpoints-with-the-curl-command">Testing endpoints with the <code>curl</code> command</h4>
<p>The <code>curl</code> command stands for "client URL". It is used to transfer data to or from a server. It can also be used to test API endpoints that helps in troubleshooting system and application errors.</p>
<p>As an example, you can use <a target="_blank" href="http://www.official-joke-api.appspot.com/"><code>http://www.official-joke-api.appspot.com/</code></a> to experiment with the <code>curl</code> command.</p>
<ul>
<li>The <code>curl</code> command without any options uses the GET method by default.</li>
</ul>
<pre><code class="lang-bash">curl http://www.official-joke-api.appspot.com/random_joke
{<span class="hljs-string">"type"</span>:<span class="hljs-string">"general"</span>,
<span class="hljs-string">"setup"</span>:<span class="hljs-string">"What did the fish say when it hit the wall?"</span>,<span class="hljs-string">"punchline"</span>:<span class="hljs-string">"Dam."</span>,<span class="hljs-string">"id"</span>:1}
</code></pre>
<ul>
<li><code>curl -o</code> saves the output to the mentioned file.</li>
</ul>
<pre><code class="lang-bash">curl -o random_joke.json http://www.official-joke-api.appspot.com/random_joke
<span class="hljs-comment"># saves the output to random_joke.json</span>
</code></pre>
<ul>
<li><code>curl -I</code> fetches only the headers.</li>
</ul>
<pre><code class="lang-bash">curl -I http://www.official-joke-api.appspot.com/random_joke
HTTP/1.1 200 OK
Content-Type: application/json; charset=utf-8
Vary: Accept-Encoding
X-Powered-By: Express
Access-Control-Allow-Origin: *
ETag: W/<span class="hljs-string">"71-NaOSpKuq8ChoxdHD24M0lrA+JXA"</span>
X-Cloud-Trace-Context: 2653a86b36b8b131df37716f8b2dd44f
Content-Length: 113
Date: Thu, 06 Jun 2024 10:11:50 GMT
Server: Google Frontend
</code></pre>
<h3 id="heading-88-linux-troubleshooting-tools-and-techniques">8.8. Linux Troubleshooting: Tools and Techniques</h3>
<h4 id="heading-system-activity-report-with-sar">System activity report with <code>sar</code></h4>
<p>The <code>sar</code> command in Linux is a powerful tool for collecting, reporting, and saving system activity information. It's part of the <code>sysstat</code> package and is widely used for monitoring system performance over time.</p>
<p>To use <code>sar</code> you first need to install <code>syssstat</code> using <code>sudo apt install sysstat</code>.</p>
<p>Once installed, start the service with <code>sudo systemctl start sysstat</code>.</p>
<p>Verify the status with <code>sudo systemctl status sysstat</code>.</p>
<p>Once the status is active, the system will start collecting various stats that you can use to access and analyze historical data. We'll see that in detail soon.</p>
<p>The syntax of the <code>sar</code> command is as follows:</p>
<pre><code class="lang-bash">sar [options] [interval] [count]
</code></pre>
<p>For example, <code>sar -u 1 3</code> will display CPU utilization statistics every second for three times.</p>
<pre><code class="lang-bash">sar -u 1 3
<span class="hljs-comment"># Output</span>
Linux 6.5.0-28-generic (zaira-ThinkPad)     04/06/24     _x86_64_    (12 CPU)

19:09:26        CPU     %user     %nice   %system   %iowait    %steal     %idle
19:09:27        all      3.78      0.00      2.18      0.08      0.00     93.96
19:09:28        all      4.02      0.00      2.01      0.08      0.00     93.89
19:09:29        all      6.89      0.00      2.10      0.00      0.00     91.01
Average:        all      4.89      0.00      2.10      0.06      0.00     92.95
</code></pre>
<p>Here are some common use cases and examples of how to use the <code>sar</code> command.</p>
<p><code>sar</code> can be used for a variety of purposes:</p>
<h5 id="heading-1-memory-usage">1. Memory usage</h5>
<p>To check memory usage (free and used), use:</p>
<pre><code class="lang-bash">sar -r 1 3

Linux 6.5.0-28-generic (zaira-ThinkPad)     04/06/24     _x86_64_    (12 CPU)

19:10:46    kbmemfree   kbavail kbmemused  %memused kbbuffers  kbcached  kbcommit   %commit  kbactive   kbinact   kbdirty
19:10:47      4600104   8934352   5502124     36.32    375844   4158352  15532012     65.99   6830564   2481260       264
19:10:48      4644668   8978940   5450252     35.98    375852   4165648  15549184     66.06   6776388   2481284        36
19:10:49      4646548   8980860   5448328     35.97    375860   4165648  15549224     66.06   6774368   2481292       116
Average:      4630440   8964717   5466901     36.09    375852   4163216  15543473     66.04   6793773   2481279       139
</code></pre>
<p>This command displays memory statistics every second three times.</p>
<h5 id="heading-2-swap-space-utilization">2. Swap space utilization</h5>
<p>To view swap space utilization statistics, use:</p>
<pre><code class="lang-bash">sar -S 1 3

sar -S 1 3
Linux 6.5.0-28-generic (zaira-ThinkPad)     04/06/24     _x86_64_    (12 CPU)

19:11:20    kbswpfree kbswpused  %swpused  kbswpcad   %swpcad
19:11:21      8388604         0      0.00         0      0.00
19:11:22      8388604         0      0.00         0      0.00
19:11:23      8388604         0      0.00         0      0.00
Average:      8388604         0      0.00         0      0.00
</code></pre>
<p>This command helps monitor the swap usage, which is crucial for systems running out of physical memory.</p>
<h5 id="heading-3-io-devices-load">3. I/O devices load</h5>
<p>To report activity for block devices and block device partitions:</p>
<pre><code class="lang-bash">sar -d 1 3
</code></pre>
<p>This command provides detailed stats about data transfers to and from block devices, and is useful for diagnosing I/O bottlenecks.</p>
<h5 id="heading-5-network-statistics">5. Network statistics</h5>
<p>To view network statistics, like number of packets received (transmitted) by the network interface:</p>
<pre><code class="lang-bash">sar -n DEV 1 3
<span class="hljs-comment"># -n DEV tells sar to report network device interfaces</span>
sar -n DEV 1 3
Linux 6.5.0-28-generic (zaira-ThinkPad)     04/06/24     _x86_64_    (12 CPU)

19:12:47        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
19:12:48           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
19:12:48       enp2s0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
19:12:48       wlp3s0     10.00      3.00      1.83      0.37      0.00      0.00      0.00      0.00
19:12:48    br-5129d04f972f      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
.
.
.

Average:        IFACE   rxpck/s   txpck/s    rxkB/s    txkB/s   rxcmp/s   txcmp/s  rxmcst/s   %ifutil
Average:           lo      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
Average:       enp2s0      0.00      0.00      0.00      0.00      0.00      0.00      0.00      0.00
...output truncated...
</code></pre>
<p>This displays network statistics every second for three seconds, helping in monitoring network traffic.</p>
<h5 id="heading-6-historical-data">6. Historical data</h5>
<p>Recall that previously we installed the <code>sysstat</code> package and ran the service. Follow the steps below to enable and access historical data.</p>
<ol>
<li><p><strong>Enable data collection:</strong> Edit the <code>sysstat</code> configuration file to enable data collection.</p>
<pre><code class="lang-bash"> sudo nano /etc/default/sysstat
</code></pre>
<p> Change <code>ENABLED="false"</code> to <code>ENABLED="true"</code>.</p>
<pre><code class="lang-bash"> vim /etc/default/sysstat
 <span class="hljs-comment">#</span>
 <span class="hljs-comment"># Default settings for /etc/init.d/sysstat, /etc/cron.d/sysstat</span>
 <span class="hljs-comment"># and /etc/cron.daily/sysstat files</span>
 <span class="hljs-comment">#</span>

 <span class="hljs-comment"># Should sadc collect system activity informations? Valid values</span>
 <span class="hljs-comment"># are "true" and "false". Please do not put other values, they</span>
 <span class="hljs-comment"># will be overwritten by debconf!</span>
 ENABLED=<span class="hljs-string">"true"</span>
</code></pre>
</li>
<li><p><strong>Configure data collection interval:</strong> Edit the cron job configuration to set the data collection interval.</p>
<pre><code class="lang-bash"> sudo nano /etc/cron.d/sysstat
</code></pre>
<p> By default, it collects data every 10 minutes. You can adjust the interval by modifying the cron job schedule. The relevant files will go to the <code>/var/log/sysstat</code> folder.</p>
</li>
<li><p><strong>View historical data:</strong> Use the <code>sar</code> command to view historical data. For example, to view CPU usage for the current day:</p>
<pre><code class="lang-bash"> sar -u
</code></pre>
<p> To view data from a specific date:</p>
<pre><code class="lang-bash"> sar -u -f /var/<span class="hljs-built_in">log</span>/sysstat/sa&lt;DD&gt;
</code></pre>
<p> Replace <code>&lt;DD&gt;</code> with the day of the month for which you want to view the data.</p>
<p> In the below command, <code>/var/log/sysstat/sa04</code> gives stats for the 4th day of the current month.</p>
</li>
</ol>
<pre><code class="lang-bash">sar -u -f /var/<span class="hljs-built_in">log</span>/sysstat/sa04
Linux 6.5.0-28-generic (zaira-ThinkPad)     04/06/24     _x86_64_    (12 CPU)

15:20:49     LINUX RESTART    (12 CPU)

16:13:30     LINUX RESTART    (12 CPU)

18:16:00        CPU     %user     %nice   %system   %iowait    %steal     %idle
18:16:01        all      0.25      0.00      0.67      0.08      0.00     99.00
Average:        all      0.25      0.00      0.67      0.08      0.00     99.00
</code></pre>
<h5 id="heading-7-real-time-cpu-interruptions">7. Real-Time CPU Interruptions</h5>
<p>To observe real-time interrupts per second served by the CPU, use this command:</p>
<pre><code class="lang-bash">sar -I SUM 1 3

<span class="hljs-comment"># Output</span>
Linux 6.5.0-28-generic (zaira-ThinkPad)     04/06/24     _x86_64_    (12 CPU)

19:14:22         INTR    intr/s
19:14:23          sum   5784.00
19:14:24          sum   5694.00
19:14:25          sum   5795.00
Average:          sum   5757.67
</code></pre>
<p>This command helps in monitoring how frequently the CPU is handling interrupts, which can be crucial for real-time performance tuning.</p>
<p>These examples illustrate how you can use <code>sar</code> to monitor various aspects of system performance. Regular use of <code>sar</code> can help in identifying system bottlenecks and ensuring that applications keep running efficiently.</p>
<h3 id="heading-89-general-troubleshooting-strategy-for-servers">8.9. General Troubleshooting Strategy for Servers</h3>
<p><strong>Why do we need to understand monitoring?</strong></p>
<p>System monitoring is an important aspect of system administration. Critical applications demand a high level of proactiveness to prevent failure and reduce the outage impact.</p>
<p>Linux offers very powerful tools to gauge system health. In this section, you'll learn about the various methods available to check your system's health and identify the bottlenecks.</p>
<h4 id="heading-find-load-average-and-system-uptime">Find load average and system uptime</h4>
<p>System reboots may occur which can sometimes mess up some configurations. To check how long the machine has been up, use the command: <code>uptime</code>. In addition to the uptime, the command also displays load average.</p>
<pre><code class="lang-bash">[user@host ~]$ uptime 19:15:00 up 1:04, 0 users, load average: 2.92, 4.48, 5.20
</code></pre>
<p>Load average is the system load over the last 1, 5, and 15 minutes. A quick glance indicates whether the system load appears to be increasing or decreasing over time.</p>
<p>Note: Ideal CPU queue is <code>0</code>. This is only possible when there are no waiting queues for the CPU.</p>
<p>Per-CPU load can be calculated by dividing load average with the total number of CPUs available.</p>
<p>To find the number of CPUs, use the command <code>lscpu.</code></p>
<pre><code class="lang-bash">lscpu
<span class="hljs-comment"># output</span>
Architecture:            x86_64
  CPU op-mode(s):        32-bit, 64-bit
  Address sizes:         48 bits physical, 48 bits virtual
  Byte Order:            Little Endian
CPU(s):                  12
  On-line CPU(s) list:   0-11
.
.
.
output omitted
</code></pre>
<p>If the load average seems to increase and does not come down, the CPUs are overloaded. There is some process that is stuck or there is a memory leakage.</p>
<h4 id="heading-calculating-free-memory">Calculating free memory</h4>
<p>Sometimes, high memory utilization might be causing problems. To check the available memory and the memory in use, use the <code>free</code> command.</p>
<pre><code class="lang-bash">free -mh
<span class="hljs-comment"># output</span>
               total        used        free      shared  buff/cache   available
Mem:            14Gi       3.5Gi       7.7Gi       109Mi       3.2Gi        10Gi
Swap:          8.0Gi          0B       8.0Gi
</code></pre>
<h4 id="heading-calculating-disk-space">Calculating disk space</h4>
<p>To ensure the system is healthy, don't forget about the disk space. To list all the available mount points and their respective used percentage, use the below command. Ideally, utilized disk spaces should not exceed 80%.</p>
<p>The <code>df</code> command provides detailed disk spaces.</p>
<pre><code class="lang-bash">df -h
Filesystem      Size  Used Avail Use% Mounted on
tmpfs           1.5G  2.4M  1.5G   1% /run
/dev/nvme0n1p2  103G   34G   65G  35% /
tmpfs           7.3G   42M  7.2G   1% /dev/shm
tmpfs           5.0M  4.0K  5.0M   1% /run/lock
efivarfs        246K   93K  149K  39% /sys/firmware/efi/efivars
/dev/nvme0n1p3  130G   47G   77G  39% /home
/dev/nvme0n1p1  511M  6.1M  505M   2% /boot/efi
tmpfs           1.5G  140K  1.5G   1% /run/user/1000
</code></pre>
<h4 id="heading-determining-process-states">Determining process states</h4>
<p>Process states can be monitored to see any stuck process with a high memory or CPU usage.</p>
<p>We saw previously that the <code>ps</code> command gives useful information about a process. Have a look at the <code>CPU</code> and <code>MEM</code> columns.</p>
<pre><code class="lang-bash">[user@host ~]$ ps aux
USER         PID %CPU %MEM    VSZ   RSS TTY      STAT START   TIME COMMAND
 runner         1  0.1  0.0 1535464 15576 ?       S  19:18   0:00 /inject/init
 runner        14  0.0  0.0  21484  3836 pts/0    S   19:21   0:00 bash --norc
 runner        22  0.0  0.0  37380  3176 pts/0    R+   19:23   0:00 ps aux
</code></pre>
<h4 id="heading-real-time-system-monitoring">Real-time system monitoring</h4>
<p>Real time monitoring gives a window into the realtime system state.</p>
<p>One utility you can use to do this is the <code>top</code> command.</p>
<p>The top command displays a dynamic view of the system's processes, displaying a summary header followed by a process or thread list. Unlike its static counterpart <code>ps</code>, <code>top</code> continuously refreshes the system stats.</p>
<p>With <code>top</code>, you can see well-organised details in a compact window. There a number of flags, shortcuts, and highlighting methods that come along with <code>top</code>.</p>
<p>You can also kill processes using <code>top</code>. For that, press <code>k</code> and then enter the process id.</p>
<h4 id="heading-interpreting-logs">Interpreting logs</h4>
<p>System and application logs carry tons of information about what the system is going through. They contain useful information and error codes that point towards errors. If you search for error codes in logs, issue identification and rectification time can be greatly reduced.</p>
<h4 id="heading-network-ports-analysis">Network ports analysis</h4>
<p>The network aspect should not be ignored as network glitches are common and may impact the system and traffic flows. Common network issues include port exhaustion, port choking, unreleased resources, and so on.</p>
<p>To identify such issues, we need to understand port states.</p>
<p>Some of the port states are explained briefly here:</p>
<div class="hn-table">
<table>
<thead>
<tr>
<td><strong>State</strong></td><td><strong>Description</strong></td></tr>
</thead>
<tbody>
<tr>
<td>LISTEN</td><td>Represents ports that are waiting for a connection request from any remote TCP and port.</td></tr>
<tr>
<td>ESTABLISHED</td><td>Represents connections that are open and data received can be delivered to the destination.</td></tr>
<tr>
<td>TIME WAIT</td><td>Represents waiting time to ensure acknowledgment of its connection termination request.</td></tr>
<tr>
<td>FIN WAIT2</td><td>Represents waiting for a connection termination request from the remote TCP.</td></tr>
</tbody>
</table>
</div><p>Let's explore how we can analyze port-related information in Linux.</p>
<p><strong>Port ranges:</strong> Port ranges are defined in the system, and range can be increased/decreased accordingly. In the below snippet, the range is from <code>15000</code> to <code>65000</code>, which makes a total of <code>50000</code> (65000 - 15000) available ports. If utilized ports are reaching or exceeding this limit, then there is an issue.</p>
<pre><code class="lang-bash">[user@host ~]$ /sbin/sysctl net.ipv4.ip_local_port_range
net.ipv4.ip_local_port_range = 15000    65000
</code></pre>
<p>The error reported in logs in such cases can be <code>Failed to bind to port</code> or <code>Too many connections</code>.</p>
<h4 id="heading-identifying-packet-loss">Identifying packet loss</h4>
<p>In system monitoring, we need to ensure that the outgoing and incoming communication is intact.</p>
<p>One helpful command is <code>ping</code>. <code>ping</code> hits the destination system and brings the response back. Note the last few lines of statistics that show packet loss percentage and time.</p>
<pre><code class="lang-bash"><span class="hljs-comment"># ping destination IP</span>
[user@host ~]$ ping 10.13.6.113
 PING 10.13.6.141 (10.13.6.141) 56(84) bytes of data.
 64 bytes from 10.13.6.113: icmp_seq=1 ttl=128 time=0.652 ms
 64 bytes from 10.13.6.113: icmp_seq=2 ttl=128 time=0.593 ms
 64 bytes from 10.13.6.113: icmp_seq=3 ttl=128 time=0.478 ms
 64 bytes from 10.13.6.113: icmp_seq=4 ttl=128 time=0.384 ms
 64 bytes from 10.13.6.113: icmp_seq=5 ttl=128 time=0.432 ms
 64 bytes from 10.13.6.113: icmp_seq=6 ttl=128 time=0.747 ms
 64 bytes from 10.13.6.113: icmp_seq=7 ttl=128 time=0.379 ms
 ^C
 --- 10.13.6.113 ping statistics ---
 7 packets transmitted, 7 received,0% packet loss, time 6001ms
 rtt min/avg/max/mdev = 0.379/0.523/0.747/0.134 ms
</code></pre>
<p>Packets can also be captured at runtime using <code>tcpdump</code>. We'll look into it later.</p>
<h4 id="heading-gathering-stats-for-issue-post-mortem">Gathering stats for issue post mortem</h4>
<p>It is always a good practice to gather certain stats that would be useful for identifying the root cause later. Usually, after system reboot or services restart, we loose the earlier system snapshot and logs.</p>
<p>Below are some of the methods to capture system snapshot.</p>
<ul>
<li><strong>Logs Backup</strong></li>
</ul>
<p>Before making any changes, copy log files to another location. This is crucial for understanding what condition the system was in during time of issue. Sometimes log files are the only window to look into past system states as other runtime stats are lost.</p>
<ul>
<li><strong>TCP Dump</strong></li>
</ul>
<p>Tcpdump is a command-line utility that allows you to capture and analyze incoming and outgoing network traffic. It is mostly used to help troubleshoot network issues. If you feel that system traffic is being impacted, take <code>tcpdump</code> as follows:</p>
<pre><code class="lang-bash">sudo tcpdump -i any -w

<span class="hljs-comment"># Where,</span>
<span class="hljs-comment"># -i any captures traffic from all interfaces</span>
<span class="hljs-comment"># -w specifies the output filename</span>

<span class="hljs-comment"># Stop the command after a few mins as the file size may increase</span>
<span class="hljs-comment"># use file extension as .pcap</span>
</code></pre>
<p>Once <code>tcpdump</code> is captured, you can use tools like Wireshark to visually analyze the traffic.</p>
<h2 id="heading-810-diagnosing-hardware-problems">8.10 <strong>Diagnosing Hardware Problems</strong></h2>
<p>Troubleshooting unexpected issues is a part of the learning process. Sometimes, you may notice frequent segmentation faults (<code>SIGSEGV</code>), overheating, or random crashes across unrelated applications. The issue could either be software or hardware related. While software-related issues depend on the specific application itself, hardware issues can be diagnosed with some standard steps.</p>
<p>In this section, we will discuss how to diagnose and rule out hardware issues related to memory, CPU, system sensors, power supply, and more.</p>
<h3 id="heading-8101-analyzing-memory-performance"><strong>8.10.1 Analyzing Memory Performance</strong></h3>
<p><strong>Determine Available RAM</strong></p>
<p>If you feel your system is getting slow and taking longer to finish tasks, check your system's available memory. This will ensure there is enough available memory including the swap memory.</p>
<p>The command to check available memory is <code>free -mh</code>, where <code>-h</code> is for human-readable output and <code>-m</code> is for displaying memory in MB.</p>
<pre><code class="lang-bash">free -mh
               total        used        free      shared  buff/cache   available
Mem:            14Gi       5.1Gi       2.4Gi        77Mi       7.3Gi       9.3Gi
Swap:          4.0Gi          0B       4.0Gi
</code></pre>
<p>In the above output, look at the "available" column in the "Mem" row. This shows how much RAM is free for use.</p>
<p>Another way to check the memory in real time is to use the <code>top</code> command. There are 2 ways to do this:</p>
<ul>
<li><p>When you are in <code>top</code>, press <code>Shift + M</code> to sort the processes by memory usage.</p>
</li>
<li><p>Alternately, press <code>m</code> to see the memory usage in a progress bar like format:</p>
</li>
</ul>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739275886121/f1695a67-13d6-4222-b71c-07176a52acb8.png" alt="f1695a67-13d6-4222-b71c-07176a52acb8" class="image--center mx-auto" width="1350" height="286" loading="lazy"></p>
<p>If you see the memory consumed near to <code>100%</code>, you might want to consider identifying the process that is consuming the memory and take necessary action. You might also want to consider adding more memory to your system.</p>
<p><strong>Run a stress test on your hardware</strong></p>
<p>The <code>memtester</code> command is a utility used for diagnosing memory-related issues by stressing the memory and checking for faults. It is often used in situations where you suspect faulty RAM might be causing system instability or crashes.</p>
<p>Here's how to use it effectively:</p>
<ul>
<li><p>First, install <code>memtester</code>.</p>
<pre><code class="lang-bash">  sudo apt install memtester
</code></pre>
</li>
<li><p>Determine the amount of RAM to test and the number of passes you’d like your RAM to go through. In the command below, <code>1G</code> is the amount of RAM to test (1 GB), and <code>5</code> is the number of test passes:</p>
<pre><code class="lang-bash">  sudo memtester 1G 5
</code></pre>
</li>
</ul>
<p>If all tests pass, your RAM is likely error-free. If errors are reported, your RAM might be faulty and could require replacement or further inspection. You can always run the test again with a different amount of RAM or test passes.</p>
<p>Note that, you shouldn't test too much memory at once, as your system also needs memory for running processes. If you have more RAM than can be tested at once, test in smaller segments sequentially.</p>
<p>Below is a snippet of the <code>memtester</code> output if all tests pass. Notice the <code>”ok”</code> status for each test.</p>
<pre><code class="lang-bash">memtester version 4.5.1 (64-bit)
Copyright (C) 2001-2020 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).

pagesize is 4096
pagesizemask is 0xfffffffffffff000
want 1024MB (1073741824 bytes)
got  1024MB (1073741824 bytes), trying mlock ...locked.
Loop 1/5:
  Stuck Address       : ok
  Random Value        : ok
  Compare XOR         : ok
  Compare SUB         : ok
  Compare MUL         : ok
  Compare DIV         : ok
  Compare OR          : ok
  Compare AND         : ok
  Sequential Increment: ok
  Solid Bits          : ok
  Block Sequential    : ok
  Checkerboard        : ok
  Bit Spread          : ok
  Bit Flip            : ok
  Walking Ones        : ok
  Walking Zeroes      : ok
  8-bit Writes        : ok
  16-bit Writes       : ok
.
.
.
</code></pre>
<p>Below is a snippet of the output if a test fails. Notice the <code>FAILURE</code> status for each test.</p>
<pre><code class="lang-bash">memtester version 4.5.1 (64-bit)
Copyright (C) 2001-2020 Charles Cazabon.
Licensed under the GNU General Public License version 2 (only).

pagesize is 4096
pagesizemask is 0xfffffffffffff000
want 1024MB (1073741824 bytes)
got  1024MB (1073741824 bytes), trying mlock ...locked.
Loop 1/5:
  Stuck Address       : testing   1FAILURE: possible bad address line at offset 0x25378a58.
Skipping to next <span class="hljs-built_in">test</span>...
  Random Value        : FAILURE: 0x4df704aaafdf8848 != 0x4df704aaafdfc848 at offset 0x05379a48.
  Compare XOR         : ok
  Compare SUB         : ok
  Compare MUL         : ok
  Compare DIV         : ok
  Compare OR          : ok
  Compare AND         : ok
  Sequential Increment: ok
  Solid Bits          : testing   6FAILURE: 0x00000000 != 0x00004000 at offset 0x05379a48.
  Block Sequential    : testing   3FAILURE: 0x303030303030303 != 0x303030303034303 at offset 0x05379a48.
  Checkerboard        : testing   0FAILURE: 0xaaaaaaaaaaaaaaaa != 0xaaaaaaaaaaaaeaaa at offset 0x05379a48.
  Bit Spread          : testing  12FAILURE: 0xffffffffffffafff != 0xffffffffffffefff at offset 0x05379a48.
  Bit Flip            : testing   0FAILURE: 0x00000001 != 0x00004001 at offset 0x05379a48.
  Walking Ones        : ok
  Walking Zeroes      : testing   0FAILURE: 0x00000001 != 0x00001001 at offset 0x053af9f8.
  8-bit Writes        : -FAILURE: 0x57c7c8ba7d6f5b3b != 0x57c7c8ba7d6f1b3b at offset 0x0537da28.
  16-bit Writes       : -FAILURE: 0xd7768894fbf79099 != 0xd7768894fbf7d099 at offset 0x05379a48.
FAILURE: 0xfffc5633ffefca5d != 0xfffc5633ffefda5d at offset 0x053a5a38.
.
.
.
</code></pre>
<p>If errors persist across all test loops, it strongly suggests hardware issues, not transient software glitches.</p>
<h3 id="heading-8102-identifying-overheating-issues"><strong>8.10.2 Identifying Overheating Issues</strong></h3>
<p>Overheating can cause unexpected errors and crashes. To diagnose overheating issues, you can use a command line utility <code>lm-sensors</code>.</p>
<p><code>lm-sensors</code> allow syou monitor hardware health by reading data from various sensors. It provides information about system temperatures, voltages, and fan speeds.</p>
<p>Here's how you can identify and monitor your system temperature using <code>lm-sensors</code>:</p>
<ul>
<li><p>First, install <code>lm-sensors</code>:</p>
<pre><code class="lang-bash">  sudo apt install lm-sensors
</code></pre>
</li>
<li><p>Detect the available sensors on your system:</p>
<pre><code class="lang-bash">  sudo sensors-detect
</code></pre>
<p>  Follow the prompts and answer “YES” to detect the available sensors on your system.</p>
</li>
<li><p>Once the available sensors are detected, you can view the temperature of your system using the <code>sensors</code> command:</p>
<pre><code class="lang-bash">  sensors
</code></pre>
<p>  In the output below, you can see the temperature reading at the edge of the GPU, which is 41.0 degrees Celsius. You can also see other pieces of information like voltage supplied, power consumption and voltage supplied.</p>
<pre><code class="lang-bash">  amdgpu-pci-0400
  Adapter: PCI adapter
  vddgfx:      731.00 mV 
  vddnb:       687.00 mV 
  edge:         +41.0°C  
  PPT:           7.00 W
</code></pre>
<p>  Using <code>lm-sensors</code> ensures that the system is operating within safe parameters. It helps to detect potential hardware problems early and take corrective actions to prevent hardware damage.</p>
</li>
</ul>
<h3 id="heading-8103-evaluating-hard-drive-health"><strong>8.10.3 Evaluating Hard Drive Health</strong></h3>
<p>Disk errors can also cause application crashes. To identify disk issues, you can run disk check using <code>smartmontools</code>:</p>
<ul>
<li><p>First, install <code>smartmontools</code>:</p>
<pre><code class="lang-bash">  sudo apt install smartmontools
</code></pre>
</li>
<li><p>Run a quick health check using the command below and replace <code>/dev/sdX</code> with your disk name (check with <code>lsblk</code>).</p>
<pre><code class="lang-bash">  sudo smartctl -H /dev/sdX
</code></pre>
</li>
<li><p>Here is the result I got when I ran the command on my disk <code>/dev/nvme0n1</code>:</p>
<pre><code class="lang-bash">  sudo smartctl -H /dev/nvme0n1
  smartctl 7.4 2023-08-01 r5530 [x86_64-linux-6.8.0-52-generic] (<span class="hljs-built_in">local</span> build)
  Copyright (C) 2002-23, Bruce Allen, Christian Franke, www.smartmontools.org

  === START OF SMART DATA SECTION ===
  SMART overall-health self-assessment <span class="hljs-built_in">test</span> result: PASSED
</code></pre>
</li>
<li><p>You can also run a detailed test:</p>
<pre><code class="lang-bash">  sudo smartctl -a /dev/nvme0n1
</code></pre>
</li>
</ul>
<p>The detailed test provides a full report, including:</p>
<ul>
<li><p>Temperature</p>
</li>
<li><p>Power-on hours</p>
</li>
<li><p>Error counts</p>
</li>
<li><p>Wear leveling (for SSDs), and more.</p>
</li>
</ul>
<h3 id="heading-8104-conducting-a-cpu-stress-test"><strong>8.10.4 Conducting a CPU Stress Test</strong></h3>
<p>Faulty CPUs can also lead to a number of performance issues. To test your CPU, you can use the <code>stress-ng</code> utility:</p>
<ul>
<li><p>Install <code>stress-ng</code>:</p>
<pre><code class="lang-bash">  sudo apt install stress-ng
</code></pre>
</li>
<li><p>Run a CPU stress test:</p>
<pre><code class="lang-bash">  stress-ng --cpu 4 --timeout 60
</code></pre>
</li>
</ul>
<p>In the above command, <code>4</code> is the number of CPU cores you’d like to test and <code>60</code> is the duration in seconds. The command will stress all 4 CPU cores for 60 seconds. Notice the CPU is at <code>100%</code> load during the test:</p>
<p><img src="https://cdn.hashnode.com/res/hashnode/image/upload/v1739277374316/9ab475c2-7f09-4c40-989b-e474e334935c.png" alt="9ab475c2-7f09-4c40-989b-e474e334935c" class="image--center mx-auto" width="1079" height="600" loading="lazy"></p>
<p>If the system crashes during this test, the CPU may be faulty.</p>
<h3 id="heading-8105-examining-system-logs-for-errors"><strong>8.10.5 Examining System Logs for Errors</strong></h3>
<p><code>systemd</code> is a Linux system manager responsible for booting the system, managing system processes, and handling system services.</p>
<p><code>journalctl</code> is a command to query the <code>systemd</code> journal logs. It provides detailed logging for system processes, kernel events, user applications, and more.</p>
<p>You can check system logs for hardware-related errors using the command: <code>journalctl -k | grep -iE "error|fault|panic"</code>.</p>
<p>In the logs, look for messages about:</p>
<ul>
<li><p>Memory faults.</p>
</li>
<li><p>I/O errors.</p>
</li>
<li><p>Hardware timeouts.</p>
</li>
</ul>
<p>Here is what errors in the log file can look like:</p>
<pre><code class="lang-bash">Feb 11 10:15:32 hostname kernel: [Hardware Error]: CPU 0: Machine Check: 0 Bank 4: b200000000070f0f
Feb 11 10:15:32 hostname kernel: [Hardware Error]: TSC 0 ADDR fef1c000 MISC 38a0000086 
Feb 11 10:15:32 hostname kernel: [Hardware Error]: PROCESSOR 0:306a9 TIME 1613045732 SOCKET 0 APIC 0 microcode 1f
Feb 11 10:16:45 hostname kernel: EXT4-fs error (device sda1): ext4_find_entry:1453: inode <span class="hljs-comment">#2: comm ls: reading directory lblock 0</span>
Feb 11 10:17:12 hostname kernel: [drm:drm_atomic_helper_commit_cleanup_done [drm_kms_helper]] *ERROR* [CRTC:36:pipe A] flip_done timed out
Feb 11 10:18:05 hostname kernel: Kernel panic - not syncing: Fatal exception
</code></pre>
<h3 id="heading-conclusion">Conclusion</h3>
<p>Thank you for reading the book until the end. If you found it helpful, consider sharing it with others.</p>
<p>This book doesn't end here, though. I will continue to improve it and add new materials in the future. If you found any issues or if you would like to suggest any improvements, <a target="_blank" href="https://github.com/zairahira/Mastering-Linux-Handbook">feel free to open a PR/ Issue.</a></p>
<p><strong>Stay Connected and Continue Your Learning Journey!</strong></p>
<p>Your journey with Linux doesn't have to end here. Stay connected and take your skills to the next level:</p>
<ol>
<li><p><strong>Follow Me on Social Media</strong>:</p>
<ul>
<li><p><a target="_blank" href="https://twitter.com/hira_zaira">X</a>: I share useful short form content there. My DMs are always open.</p>
</li>
<li><p><a target="_blank" href="https://www.linkedin.com/in/zaira-hira/">LinkedIn</a>: I share articles and posts on tech there. Leave a recommendation on LinkedIn and endorse me on relevant skills.</p>
</li>
</ul>
</li>
<li><p><strong>Get access to exclusive content</strong>: For one-on-one help and exclusive content go <a target="_blank" href="https://buymeacoffee.com/zairah/extras">here</a>.</p>
</li>
</ol>
<p>My <a target="_blank" href="https://www.freecodecamp.org/news/author/zaira/">articles</a> and books, like this one, are part of my mission to increase accessibility to quality content for everyone. This book will also be open to translation in other languages. Each piece takes a lot of time and effort to write. This book will be free, forever. If you've enjoyed my work and want to keep me motivated, consider <a target="_blank" href="https://buymeacoffee.com/zairah">buying me a coffee</a>.</p>
<p>Thank you once again and happy learning!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Learn to Code and Get a Developer Job [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ If you want to learn to code and get a job as a developer, you're in the right place. This book will show you how. And yes this is the full book – for free – right here on this page of freeCodeCamp. Also, I've recorded a FREE full-length audiobook ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-to-code-book/</link>
                <guid isPermaLink="false">66b8d493f8e5d39507c4c102</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Career ]]>
                    </category>
                
                    <category>
                        <![CDATA[ education ]]>
                    </category>
                
                    <category>
                        <![CDATA[ learn to code ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Quincy Larson ]]>
                </dc:creator>
                <pubDate>Thu, 11 Jul 2024 23:52:00 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/06/Learn-to-Code-and-Get-a-Developer-Job-Book.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you want to learn to code and get a job as a developer, you're in the right place. This book will show you how.</p>
<p>And yes this is the full book – for free – right here on this page of freeCodeCamp.</p>
<p>Also, I've recorded a FREE full-length audiobook version of this book, which I published as episode #100 of The freeCodeCamp Podcast. You can search for it in your favorite podcast player. Be sure to subscribe. I've also embedded it below for your convenience.</p>
<div class="embed-wrapper"><iframe src="https://play.libsyn.com/embed/episode/id/28380047/height/192/theme/modern/size/large/thumbnail/yes/custom-color/2a4061/time-start/00:00:00/playlist-height/200/direction/backward/download/yes" height="192" width="100%" style="border:none" title="Embedded content" loading="lazy"></iframe></div>

<p>A few years back, one of the Big 5 book publishers from New York City reached out to me about a book deal. I met with them, but didn't have time to write a book.</p>
<p>Well, I finally had time. And I decided to just publish this book for free, right here on freeCodeCamp.</p>
<p>Information wants to be free, right? 🙂</p>
<p>It will take you a few hours to read all this. But this is it. My insights into learning to code and getting a developer job.</p>
<p>I learned all of this while:</p>
<ul>
<li>learning to code in my 30s</li>
<li>then working as a software engineer</li>
<li>then running freeCodeCamp.org for the past 8 years. Today, more than a million people visit this website each day to learn about math, programming, and computer science.</li>
</ul>
<p>I was an English teacher who had never programmed before. And I was able to learn enough coding to get my first software development job in just one year.</p>
<p>All without spending money on books or courses.</p>
<p>(I did spend money to travel to nearby cities and participate in tech events. And as you'll see later in the book, this was money well spent.)</p>
<p>After working as a software engineer for a few years, I felt ready. I wanted to teach other people how to make this career transition, too.</p>
<p>I built several technology education tools that nobody was interested in using. But then one weekend, I built freeCodeCamp.org. A vibrant community quickly gathered around it.</p>
<p>Along the way, we all helped each other. And today, people all around the world have used freeCodeCamp to prepare for their first job in tech.</p>
<p>You may be thinking: I don't know if I have time to read this entire book.</p>
<p>No worries. You can bookmark it. You can come back to it and read it across as many sittings as you need to.</p>
<p>And you can share it on social media. Sharing: "check out this book I'm reading" and linking to it is a surprisingly effective way to convince yourself to finish reading a book.</p>
<p>I say this because I'm not trying to sell you this book. You already "bought" this book when you opened this webpage. Now my goal is to reassure you that it <strong>will</strong> be worth investing your time to finish reading this book. 😉</p>
<p>I promise to be respectful of your time. There's no hype or fluff here – just blunt, actionable tips.</p>
<p>I'm going to jam as much insight as I can into every chapter of this book.</p>
<p>Which reminds me: where's the table of contents?</p>
<p>Ah. Here it is:</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-preface-who-is-this-book-for">Preface: Who is this book for?</a></li>
<li><a class="post-section-overview" href="#heading-500-word-executive-summary">500 Word Executive Summary</a></li>
<li><a class="post-section-overview" href="#heading-chapter-1-how-to-build-your-skills">Chapter 1: How to Build Your Skills</a></li>
<li><a class="post-section-overview" href="#heading-chapter-2-how-to-build-your-network">Chapter 2: How to Build Your Network</a></li>
<li><a class="post-section-overview" href="#heading-chapter-3-how-to-build-your-reputation">Chapter 3: How to Build Your Reputation</a></li>
<li><a class="post-section-overview" href="#heading-chapter-4-how-to-get-paid-to-code-freelance-clients-and-the-job-search">Chapter 4: How to Get Paid to Code – Freelance Clients and the Job Search</a></li>
<li><a class="post-section-overview" href="#heading-chapter-5-how-to-succeed-in-your-first-developer-job">Chapter 5: How to Succeed in Your First Developer Job</a></li>
<li><a class="post-section-overview" href="#heading-epilogue-you-can-do-this">Epilogue: You Can Do This</a></li>
</ol>
<h2 id="heading-preface-who-is-this-book-for">Preface: Who is This Book For?</h2>
<p>This book is for anyone who is considering a career in software development.</p>
<p>If you're looking for a career that's flexible, high-paying, and involves a lot of creative problem solving, software development may be for you.</p>
<p>Of course, each of us approaches our own coding journey with certain resources: <strong>time</strong>, <strong>money</strong>, and <strong>opportunity</strong>.</p>
<p>You may be older, and may have kids or elderly relatives you're taking care of. So you may have less <strong>time</strong>.</p>
<p>Or you may be younger, and may have had less time to build up any savings, or acquire skills that boost your income. So you may have less <strong>money</strong>.</p>
<p>And you may live far away from the major tech cities like San Francisco, Berlin, Tokyo, or Bengaluru.</p>
<p>Or you may live with disabilities, physical or mental. Agism, racism, and sexism are real. Immigration status can complicate the job search. So can a criminal record.</p>
<p>So you may have less <strong>opportunity</strong>.</p>
<p>Learning to code and getting a developer job is going to be harder for some people than it will be for others. Everyone approaches this challenge from their own starting point, with whatever resources they happen to have on hand.</p>
<p>But wherever you may be starting out from – in terms of time, money, and opportunity – I'll do my best to give you actionable advice.</p>
<p>In other words: don't worry – you are in the right place.</p>
<h4 id="heading-a-quick-note-on-terminology">A Quick Note on Terminology</h4>
<p>Whenever I use new terms, I'll do my best to define them.</p>
<p>But there are a few terms I'll be saying all the time.</p>
<p>I'll use the words "programming" and "coding" interchangeably.</p>
<p>I'll use the word "app" as it was intended – as shorthand for any sort of application, regardless of whether it runs on a phone, laptop, game console, or refrigerator. (Sorry, Steve Jobs. iPhone does not have a monopoly on the word app.)</p>
<p>I will also use the words "software engineer" and "software developer" interchangeably.</p>
<p>You may encounter people in tech who take issue with this. As though software engineering is some fancy-pants field with a multi-century legacy, like mechanical engineering or civil engineering are. Who knows – maybe that will be true for your grandkids. But we are still very much in the early days of software development as a field.</p>
<p>I'll just drop this quote here for you, in case you feel awkward calling yourself a software engineer:</p>
<blockquote>
<p>"If builders built buildings the way programmers wrote programs, then the first woodpecker that came along would destroy civilization." – Gerald Weinberg, Programmer, Author, and University Professor</p>
</blockquote>
<h3 id="heading-can-anyone-learn-to-code">Can Anyone Learn to Code?</h3>
<p>Yes. I believe that any sufficiently motivated person can learn to code. At the end of the day, learning to code is a motivational challenge – not a question of aptitude.</p>
<p>On the savannas of Africa – where early humans lived for thousands of years before spreading to Europe, Asia, and the Americas – were there computers?</p>
<p>Programming skills were never something that was selected for over the millennia. Computers as we know them (desktops, laptops, smartphones) emerged in the 80s, 90s, and 00s.</p>
<p>Yes – I do believe that aptitude plays a part. But at the end of the day, anyone who wants to become a professional developer will need to put in time at the keyboard.</p>
<p>A vast majority of people who try to learn to code will get frustrated and give up.</p>
<p>I sure did. I got frustrated and gave up. Several times.</p>
<p>But like other people who eventually succeeded, I kept coming back after a few days, and tried again.</p>
<p>I say all this because I want to acknowledge: learning to code and getting a developer job is hard. And it's even harder for some people than others, due to circumstance.</p>
<p>I'm not going to pretend to have faced true adversity in learning to code. Yes, I was in my 30s, and I had no formal background in programming or computers science. But consider this:</p>
<p>I grew up middle class in the United States – a 4th-generation American from an English-speaking home. I went to university. My father went to university. And his father went to university. (His parents before him were farmers from Sweden.)</p>
<p>I benefitted from a sort of intergenerational privilege. A momentum that some families are able to pick up over time when they are not torn apart by war, famine, or slavery.</p>
<p>So that is my giant caveat to you: I am not some motivational figure to pump you up to overcome adversity.</p>
<p>If you need inspiration, there are a ton of people in the developer community who have overcome real adversity. You can seek them out.</p>
<p>I'm not trying to elevate the field of software development. I'm not going to paint pictures of science fiction utopias that can come about if everyone learns to code.</p>
<p>Instead, I'm just going to give you practical tips for how you can acquire these skills. And how you can go get a good job, so you can provide for your family.</p>
<p>There's nothing wrong with learning to code because you want a good, stable job.</p>
<p>There's nothing wrong with learning to code so you can start a business.</p>
<p>You may encounter people who say that you must be so passionate about coding that you dream about it. That you clock out of your full-time job, then spend all weekend contributing to open source projects.</p>
<p>I do know people who are <em>that</em> passionate about coding. But I also know plenty of people who, after finishing a hard week's work, just want to go spend time in nature, or play board games with friends.</p>
<p>People generally enjoy doing things they're good at doing. And you can develop a reasonable level of passion for coding just by getting better at coding.</p>
<p>So in short: who is this book for? Anyone who wants to get better at coding, and get a job as a developer. That's it.</p>
<p>You don't need to be a self-proclaimed "geek", an introvert, or an ideologically-driven activist. Or any of those stereotypes.</p>
<p>It's fine if you are. But you don't need to be.</p>
<p>So if that's you – if you're serious about learning to code well enough to get paid to code – this book is for you.</p>
<p>And you should start by reading this quick summary of the book. And then reading the rest of it.</p>
<h2 id="heading-500-word-executive-summary">500 Word Executive Summary</h2>
<p>Learning to code is hard. Getting a job as a software developer is even harder. But for many people, it's worth the effort.</p>
<p>Coding is a high-paying, intellectually challenging, creatively rewarding field. There is a clear career progression ahead of you: senior developer, tech lead, engineering manager, CTO, and perhaps even CEO.</p>
<p>You can find work in just about any industry. About two thirds of developer jobs are outside of what we traditionally call "tech" – in agriculture, manufacturing, government, and service industries like banking and healthcare.</p>
<p>If you're worried your job might be automated before you reach retirement, consider this: coding is the act of automating things. Thus it is by definition the last career that will be completely automated.</p>
<p>Automation will impact coding. It already has. For decades.</p>
<p>Generative AI tools like GPT-4 and Copilot can help us move from Imperative Programming – where you tell computers exactly what to do – closer to Declarative Programming – where you give computers higher-level objectives. In other words: Star Trek-style programming.</p>
<p>You should still learn math even though we now have calculators. And you should still learn programming even though we now have AI tools that can write code.</p>
<p>Have I sold you on coding as a career for you?</p>
<p>Good. Here's how to break into the field.</p>
<h3 id="heading-build-your-skills">Build your skills.</h3>
<p>You need to learn:</p>
<ul>
<li>Front End Development: HTML, CSS, JavaScript</li>
<li>Back End Development: SQL, Git, Linux, and Web Servers</li>
<li>Scientific Computing: Python and its many libraries</li>
</ul>
<p>These are all mature, 20+ year old technologies. Whichever company you work for, you will almost certainly use most of these tools.</p>
<p>The best way to learn these tools is to build projects. Try to code at least some every day. If you do the freeCodeCamp curriculum from top to bottom, you'll learn all of this and build dozens of projects.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/Learn_to_Code_-_For_Free_-_Coding_Courses_for_Busy_People_--.png" alt="Image" width="600" height="400" loading="lazy">
<em>Some of the certifications in the freeCodeCamp core curriculum.</em></p>
<h3 id="heading-build-your-network">Build your network.</h3>
<p>So much of getting a job is who you know.</p>
<p>It's OK to be an introvert, but you do need to push your boundaries.</p>
<p>Create GitHub, Twitter, LinkedIn, and Discord accounts.</p>
<p>Go to tech meetups and conferences. Travel if you have to. (Most of your "learn to code" budget should go toward travel and event tickets – not books and courses.)</p>
<p>Greet people who are standing by themselves. Let others do most of the talking, and really listen. Remember people's names.</p>
<p>Add people on LinkedIn, follow them on Twitter, and go to after-parties.</p>
<h3 id="heading-build-your-reputation">Build your reputation.</h3>
<p>Share short video demos of your projects.</p>
<p>Keep applying to speak at bigger and bigger conferences.</p>
<p>Hang out at hackerspaces and help people who are even newer to coding than you.</p>
<p>Contribute to open source. The work is similar to professional software development.</p>
<p><strong>Build your Skills, Network, and Reputation at the same time.</strong> Don't let yourself procrastinate the scariest parts.</p>
<p>Instead of applying for jobs through the "front door" use your network to land job interviews through the "side door." Recruiters can help, too.</p>
<p>Keep interviewing until you start getting job offers. You don't need to accept the first offer you get, though. Be patient.</p>
<p>Your first developer job will be the hardest. Try to stay there for at least 2 years, and essentially get paid to learn.</p>
<p>The real learning begins once you're on-the-job, working alongside a team, and with large legacy codebases.</p>
<p>Most importantly, sleep and exercise.</p>
<p>Any sufficiently-motivated person can learn to code well enough to get a job as a developer.</p>
<p>It's just a question of how badly you want it, and how persistent you can be in the job search.</p>
<p>Remember: you can do this.</p>
<h2 id="heading-this-book-is-dedicated-to-the-global-freecodecamp-community">This Book is Dedicated to the Global freeCodeCamp Community.</h2>
<p>Thank you to all of you who have supported our charity and our mission over the past 9 years.</p>
<p>It is through your volunteerism and through your philanthropy that we've been able to help so many people learn to code and get their first developer job.</p>
<p>The community has grown so much from the humble open source project I first deployed in 2014. I am now just a small part of this global community.</p>
<p>It is a privilege to still be here, working alongside you all. Together, we face the fundamental problems of our time. Access to information. Access to education. And access to the tools that are shaping the future.</p>
<p>These are still early days. I have no illusion that everyone will know how to code within my lifetime. But just like the Gutenberg Bible accelerated literacy in 1455, we can continue to accelerate technology literacy through free, open learning resources.</p>
<p>Again, thank you all.</p>
<p>And special thanks to Abbey Rennemeyer for her editorial feedback, and to Estefania Cassingena Navone for designing the book cover.</p>
<p>And now, the book.</p>
<h2 id="heading-chapter-1-how-to-build-your-skills">Chapter 1: How to Build Your Skills</h2>
<blockquote>
<p>"Every artist was first an amateur." ― Ralph Waldo Emerson</p>
</blockquote>
<p>The road to knowing how to code is a long one.</p>
<p>For me, it was an ambiguous one.</p>
<p>But it doesn't have to be like that for you.</p>
<p>In this chapter, I'm going to share some strategies for learning to code as smoothly as possible.</p>
<p>First, allow me to walk you through how I learned to code back in 2011.</p>
<p>Then I'll share what I learned from this process.</p>
<p>I'll show you how to learn much more efficiently than I did.</p>
<h3 id="heading-story-time-how-did-a-teacher-in-his-30s-teach-himself-to-code">Story Time: How Did a Teacher in His 30s Teach Himself to Code?</h3>
<p>I was a teacher running an English school. We had about 100 adult-aged students who had traveled to California from all around the world. They were learning advanced English so they could get into grad school.</p>
<p>Most of our school's teachers loved teaching. They loved hanging out with students around town, and helping them improve their conversational English.</p>
<p>What these teachers didn't love was paperwork: Attendance reports. Grade reports. Immigration paperwork.</p>
<p>I wanted our teachers to be able to spend more time with students. And less time chained to their desks doing paperwork.</p>
<p>But what did I know about computers?</p>
<p>Programming? Didn't you have to be smart to do that? I could barely configure a WiFi router. And I sucked at math.</p>
<p>Well one day I just pushed all that aside and thought "You know what: I'm going to give it a try. What do I have to lose?"</p>
<p>I started googling questions like "how to automatically click through websites." And "how to import data from websites into Excel."</p>
<p>I didn't realize it at the time, but I was learning how to automate workflows.</p>
<p>And the learning began. First with Excel macros. Then with a tool called AutoHotKey where you can program your mouse to move to certain coordinates of a screen, click around, copy text, then move to different coordinates and paste it.</p>
<p>After a few weeks of grasping in the dark, I figured out how to automate a few tasks. I could open an Excel spreadsheet and a website, run my script, then come back 10 minutes later and the spreadsheet would be fully populated.</p>
<p>It was the work of an amateur. What developers might call a "dirty hack". But it got the job done.</p>
<p>I used my newfound automation skills to continue streamlining the school.</p>
<p>Soon teachers barely had to touch a computer. I was doing the work of several teachers, just with my rudimentary skills.</p>
<p>This had a visible impact on the school. So much of our time had been tied up with rote work on the computer. And now we were free.</p>
<p>The teachers were happier. They spent more time with students.</p>
<p>The students were happier. They told all their friends back in their home country "you've got to check out this school."</p>
<p>Soon we were one of the most successful schools in the entire school system.</p>
<p>This further emboldened me. I remember thinking to myself: "Maybe I <strong>can</strong> learn to code."</p>
<p>I knew some software engineers from my board game night. They had traditional backgrounds, with degrees from Cal Tech, Harvey Mudd, and other famous Computer Science programs.</p>
<p>At the time, it was far less common for people in their 30s to learn to code.</p>
<p>I worked up the courage to share my dreams with some of these friends.</p>
<p>I wanted to learn to how program properly. I wanted to be able to write code for a living like they did. And to maybe even write software that could power schools.</p>
<p>I would share these dreams up with my developer friends. "I want to do what you do."</p>
<p>But they would sort of shrug. Then they'd say something like:</p>
<p>"I mean, you could try. But you're going to have to drink an entire ocean of knowledge."</p>
<p>And: "It's a pretty competitive field. How are you going to hang with people who grew up coding from an early age?"</p>
<p>And: "You're already doing fine as a teacher. Why don't you just stick with what you're good at?"</p>
<p>And that would knock me off course for a few weeks. I would go on long, soul-searching walks at night. I would ponder my future under the stars. Were these people right? I mean – they would know, right?</p>
<p>But every morning I'd be back at my desk. Watching my scripts run. Watching my reports compile themselves at superhuman speeds. Watching as my computer did my bidding.</p>
<p>A thought did occur to me: maybe these friends were just trying to save me from heartache. Maybe they just don't know anyone who learned to code in their 30s. So they don't think it's possible.</p>
<p>It's like... for years doctors thought that it would be impossible for someone to run a mile in 4 minutes. They thought your heart would explode from running so fast.</p>
<p>But then somebody managed to do it. And his heart did not explode.</p>
<p>Once Roger Bannister – a 25-year old Oxford student – broke that psychological barrier – a ton of other people did it, too. To date, more than 1,000 people have run a sub-4 minute mile.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/Roger-Bannister-1951_jpg__1269-1600_.png" alt="Image" width="600" height="400" loading="lazy">
<em>Roger Bannister running like a a champ. (Image: Britannica)</em></p>
<p>And it's not like I was doing something as bold and unprecedented as running a 4 minute mile here. Plenty of famous developers have managed to teach themselves coding over the years.</p>
<p>Heck, Ada Lovelace taught herself programming in the 1840s. And she didn't even have a working computer. She just had an understanding of how her friend Charles Babbage's computer would work in theory.</p>
<p>She wrote several of the first computer algorithms. And she's widely regarded as the world's first computer programmer. Nobody taught her. Because there was nobody to teach her. Whatever self doubt she may have had, she clearly overcame it.</p>
<p>Now, I was no Ada Lovelace. I was just some teacher who already had a working computer, a decent internet connection, and the ability to search through billions of webpages with Google.</p>
<p>I cracked my knuckles and narrowed my gaze. I was going to do this.</p>
<h3 id="heading-stuck-in-tutorial-hell">Stuck in Tutorial Hell</h3>
<blockquote>
<p>"If you work for 10 years, do you get 10 years of experience or do you get 1 year of experience 10 times? You have to reflect on your activities to get true experience. If you make learning a continuous commitment, you’ll get experience. If you don’t, you won’t, no matter how many years you have under your belt." – Steve McConnell, Software Engineer</p>
</blockquote>
<p>I spent the next few weeks googling around, and doing random tutorials that I encountered online.</p>
<p>Oh look, a Ruby tutorial.</p>
<p>Uh-oh, it's starting to get hard. I'm getting error messages not mentioned in the tutorial. Hm... what's going on here...</p>
<p>Oh look, a Python tutorial.</p>
<p>Human psychology is a funny thing. The moment something starts to get hard, we ask: am I doing this right?</p>
<p>Maybe this tutorial is out of date. Maybe its author didn't know what they were talking about. Does anybody even still use this programming language?</p>
<p>When you're facing ambiguous error messages hours into a coding session, the grass on the other side starts to look a lot greener.</p>
<p>It was easy to pretend I'd made progress. Time to go grab lunch.</p>
<p>I'd see a friend at the café. "How's your coding going?" they'd ask.</p>
<p>"It's going great. I already coded 4 hours today."</p>
<p>"Awesome. I'd love to see what you're building sometime."</p>
<p>"Sure thing," I'd say, knowing that I'd built nothing. "Soon."</p>
<p>Maybe I'd go to the library and check out a new JavaScript book.</p>
<p>There's that old saying that buying books gives you the best feeling in the world. Because it also feels like you're buying the time to read them.</p>
<p>And this is precisely where I found myself a few weeks into learning to code.</p>
<p>I had read the first 100 pages of several programming books, but finished none.</p>
<p>I had written the first 100 lines of code from several programming tutorials, but finished none.</p>
<p>I didn't know it, but I was trapped in place that developers lovingly call "tutorial hell."</p>
<p>Tutorial hell is where you jump from one tutorial to the next, learning and then relearning the same basic things. But never really going beyond the fundamentals.</p>
<p>Because going beyond the fundamentals? Well, that requires some real work.</p>
<h3 id="heading-it-takes-a-village-to-raise-a-coder">It Takes a Village to Raise a Coder</h3>
<p>Learning to code was absorbing all of my free time. But I wasn't making much progress. I could now type the <code>{</code> and <code>*</code> characters without looking at the keyboard. But that was about it.</p>
<p>I knew I needed help. Perhaps some Yoda-like mentor, who could teach me the ways. Yes – if such a person existed, surely that would make all the difference.</p>
<p>I found out about a nearby place called a "hackerspace." When I first heard the name, I was a bit apprehensive. Don't hackers do illegal things? I was an English teacher who liked playing board games. I was not looking for trouble.</p>
<p>Well I called the number listed and talked with a guy named Steve. I nervously asked: "You all don't do anything illegal, do you?" And Steve laughed.</p>
<p>It turns out the word "hack" is what he called an overloaded term. Yes – "to hack" can mean to maliciously break into a software system. But "to hack" can also mean something more mundane: to write computer code.</p>
<p>Something can be "hacky" meaning it's not an elegant solution. And yet you can have "a clever hack" – an ingenious trick to make your code work more efficiently.</p>
<p>In short: don't be scared of the term "hack."</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/1200x-1_jpg__1200-797_.png" alt="Image" width="600" height="400" loading="lazy">
<em>Facebook's corporate campus has the word "hack" written in giant letter on the concrete. (Image: Bloomberg)</em></p>
<p>I, for one, scarcely use the term because it's so confusing. And I think recently a lot of hackerspaces have picked up on the ambiguity. Many of them now call themselves "makerspaces" instead.</p>
<p>Because that's what a hackerspace is all about – making things.</p>
<p>Steve invited me to visit the hackerspace on Saturday afternoon. He said several developers from the area would be there.</p>
<p>The first time I walked through the doors of the Santa Barbara Hackerspace, I was blown away.</p>
<p>The place smelled like an electric fire. Its makeshift tables were lined with soldering irons, strips of LED lights, hobbyist Arduino circuit boards, and piles of Roomba vacuum robots.</p>
<p>The same Steve I'd spoken to on the phone was there, and he greeted me. He had glasses, slicked back hair, and a goatee beard. He was always smiling. And when you asked him a question, instead of responding quickly, he would nod and think for a few seconds first.</p>
<p>Steve was a passionate programmer who had studied math and philosophy at the University of California – Santa Barbara. He was still passionate about those subjects. But his real passion was Python.</p>
<p>Steve turned on the projector and gave an informal "lightning talk." He was demoing an app he'd written that would recognize QR codes in a video and replace them with images.</p>
<p>Someone in the audience pulled up a QR code on their laptop and held it in front of the camera. Steve's app then replaced the QR code with a picture of a pizza.</p>
<p>Somebody in the audience shouted, "Can you make the pizza spin?"</p>
<p>Steve opened up his code in a code editor, called Emacs, and started making changes to it in real time. He effortlessly tabbed between his code editor, his command line, and the browser the app was running in, "hot loading" updates to the code.</p>
<p>For me, this was sorcery. I couldn't believe Steve had just busted out that app over the course of few hours. And now he was adding new features on the fly, as the audience requested them.</p>
<p>I thought: "This guy is a genius."</p>
<p>And that evening, after the event ended, he and I stayed after and I told him so.</p>
<p>We ate sandwiches together. And I said to him: "I could code for my entire career and not be as good as you. I would be thrilled if after 10 years I could code even half as well as you."</p>
<p>But Steve pushed back. He said, "I'm nothing special. Don't limit yourself. If you stick with coding, you could easily surpass me."</p>
<p>Now, I didn't for a second believe the words he said to me. But just the fact that he said it gave me butterflies.</p>
<p>Here he was: a developer who believed in me. He saw me – some random teacher – the very definition of a "script kiddie" – and thought I could make it.</p>
<p>Steve and I talked late into the night. He showed me his $200 netbook computer, which even by 2011 standards was woefully underpowered.</p>
<p>"You don't need a powerful computer to build software," Steve told me. "Today's hardware is incredibly powerful. Computers are only slow because the bloated software they run makes them slow. Get an off-the-shelf laptop, wipe the hard drive, install Linux on it, and start coding."</p>
<p>I took note of the model of laptop he had and ordered the exact same one when I got home that night.</p>
<p>After a few days of debugging my new computer with Stack Overflow, I successfully installed Ubuntu. I started learning how to use the Emacs code editor. By the following Saturday, I knew a few commands, and was quick to show them off.</p>
<p>Steve nodded in approval. He said, "Awesome. But what are you building?"</p>
<p>I didn't understand what he meant. "I'm learning how to use Emacs. Check it out. I memorized..."</p>
<p>But Steve looked pensive. "That's cool and all. But you need a project. Always have a project. Then learn what you need to learn en route to finishing that project."</p>
<p>Other than a few scripts I'd written for to help the teachers at my school, I had never finished anything. But I started to see what he was saying. </p>
<p>And it started to dawn on me. All this time I had been trapped in tutorial hell, going in circles, finishing nothing.</p>
<p>Steve said, "I want you to build a project using HTML5. And next Saturday, I want you to present it at the hackerspace."</p>
<p>I was mortified at his words. But I stood up straight and said. "Sounds like a plan. I'm on it."</p>
<h3 id="heading-nobody-can-make-you-a-developer-but-you">Nobody Can Make You a Developer But You</h3>
<blockquote>
<p>"I'm trying to free your mind, Neo. But I can only show you the door. You're the one that has to walk through it." – Morpheus in the 1999 film The Matrix</p>
</blockquote>
<p>The next morning, I woke up extra early before work and googled something like "HTML5 tutorial." I already knew a lot of this from my previous time in tutorial hell. But instead of skipping ahead, I just slowed my roll and followed along exactly, typing every single command.</p>
<p>Usually once I finished a tutorial I would just go find another tutorial. But instead, I started playing with the tutorial's code. I had a simple idea for a project. I was going to make an HTML5 documentation page. And I was going to code it purely in HTML5.</p>
<p>Let me explain HTML5 real quick. It's just a newer version of HTML, which has existed since the first webpages back in the 1990s.</p>
<p>If a website was a body, HTML would be the bones. Everything else rests on top of those bones. (You can think of JavaScript as the muscles and CSS as the skin. But let's get back to the story.)</p>
<p>I knew that in HTML, you could link to different parts of the same webpage by using ID properties. So I thought: what if I put a table of contents along the left hand side? Then clicking the different items on the left would scroll down the page on the right to show those items.</p>
<p>Within half an hour, I had coded a rough prototype.</p>
<p>But it was time to report for work at the school. The entire day, all I could think about was my project, and how I should best go about finishing it.</p>
<p>I raced home, opened up my laptop, and spent the entire evening coding.</p>
<p>I copied the official (and creative commons-licensed) HTML documentation directly into my page, "hard coding" it into the HTML.</p>
<p>Then I spent about an hour on the CSS, getting everything to look right, and using absolute positioning to keep the sidebar in place.</p>
<p>I made a point to make use of as many of HTML5's new "semantic" tags as I could.</p>
<p>And boom – project finished.</p>
<p>A wave of accomplishment washed over me. I jogged to a nearby football field and ran laps around the field, celebrating. I did it. I finished a project.</p>
<p>And I decided right then and there: from here on out, everything I do is going to be a project. I'm going to be working toward some finished product.</p>
<p>The next evening I walked up to the podium, plugged in my laptop, and presented my HTML5 webpage. I answered questions from the developers there about HTML5.</p>
<p>Sometimes I'd get something wrong, and someone in the audience would say, "that doesn't sound right – let me check the documentation."</p>
<p>People weren't afraid to correct me. But they were polite and supportive. It didn't even feel like they were correcting me – it felt like they were correcting the public record – lest someone walk away with incorrect information.</p>
<p>I didn't feel any of the anxiety that I might have felt giving a talk at a teacher in-service meeting.</p>
<p>Instead I almost felt like I was part of the audience, learning alongside them.</p>
<p>After all, these tools were new and emerging. We were all trying to understand how to use them together.</p>
<p>After my talk, Steve came up to me and said, "Not bad."</p>
<p>I smiled for an awkwardly long time, not saying anything, just happy with myself.</p>
<p>Then Steve squinted and pursed his lips. He said: "Start your next project tonight."</p>
<h3 id="heading-lessons-from-my-coding-journey">Lessons from my Coding Journey</h3>
<p>We'll check in on younger Quincy's coding journey in each of the following chapters. But now I want to break down some of the lessons here. And I want to answer some of the questions you may have.</p>
<h3 id="heading-why-is-learning-to-code-so-hard">Why is Learning to Code so Hard?</h3>
<p>Learning any new skill is hard. Whether it's dribbling a soccer ball, changing the oil on a car, or speaking a new language.</p>
<p>Learning to code is hard for a few particular reasons. And some of these are unique to coding.</p>
<p>The first one is that most people don't understand exactly what coding is. Well, I'm going to tell you.</p>
<h3 id="heading-what-is-coding">What is coding?</h3>
<p>Coding is telling a computer what to do, in a way the computer can understand.</p>
<p>That's it. That's all coding really is.</p>
<p>Now, make no mistake. Communicating with computers is hard. They are "dumb" by human standards. They will do exactly what you tell them to do. But unless you're good at coding, they are probably not going to do what you <strong>want</strong> them to do.</p>
<p>You may be thinking: what about servers? What about databases? What about networks?</p>
<p>At the end of the day, these are all controlled by layers of software. Code. It's code all the way down. Eventually you reach the physical hardware, which is moving electrons around circuit boards.</p>
<p>For the first few decades of computing, developers wrote code that was "close to the metal" – often operating on the hardware directly, flipping bits from 0 to 1 and back.</p>
<p>But contemporary software development involves so many "layers of abstraction" – programs running on top of programs – that just a few lines of JavaScript code can do some really powerful things.</p>
<p>In the 1960s, a "bug" could be an insect crawling around inside a room-sized computer, and getting fried in one of the circuits.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/First_Computer_Bug-_1945.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>The first computer bug, discovered in 1945, was a moth that got trapped in the panels of a room-sized calculator computer at Harvard. (Image: Public Domain)</em></p>
<p>Today, we're writing code so many layers of abstraction above the physical hardware.</p>
<p>That is coding. It's vastly easier than it has ever been in the past. And it is getting easier to do every year. </p>
<p>I am not exaggerating when I say that in a few decades, coding will be so easy and so common that most younger people will know how to do it.</p>
<h2 id="heading-why-is-learning-to-code-still-so-hard-after-all-these-years">Why is learning to code still so hard after all these years?</h2>
<p>There are three big reasons why learning to code is so hard, even today:</p>
<ol>
<li>The tools are still primitive.</li>
<li>Most people aren't good at handling ambiguity, and learning to code is ambiguous. People get lost.</li>
<li>Most people aren't good at handling constant negative feedback. And learning to code is one brutal error message after another. People get frustrated.</li>
</ol>
<p>Now I'll discuss each of these difficulties in more detail. And I'll give you some practical strategies for overcoming each of them.</p>
<h3 id="heading-the-tools-are-still-primitive">The Tools are Still Primitive</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/TNG-S4E19-171.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>A Possessed Barclay from Star Trek: The Next Generation, programming on the Holodeck.</em></p>
<blockquote>
<p>"Computer. Begin new program. Create as follows. Work station chair. Now create a standard alphanumeric console positioned to the left hand. Now an iconic display console for the right hand. Tie both consoles into the Enterprise main computer core, utilizing neuralscan interface." - Barclay from Star Trek: The Next Generation, Season 4 Episode 19: "The Nth Degree"</p>
</blockquote>
<p>This is how people might program in the future. It's an example from my favorite science fiction TV show, Star Trek: The Next Generation.</p>
<p>Every character in Star Trek can code. Doctors, security officers, pilots. Even little Wesley Crusher (played by child actor Wil Wheaton) can get the ship's computer to do his bidding.</p>
<p>Sure – one of the reasons everyone can code is that they live in a post-scarcity 24th-century society, with access to free high quality education.</p>
<p>Another reason is that in the future, coding will be much, much easier. You just tell a computer precisely what to do, and – if you're precise enough – the computer does it.</p>
<p>What if programming was as easy as just saying instructions to a computer in plain English?</p>
<p>Well, we've already made significant progress toward this goal. Think of our grandmothers, running between room-sized mainframe computers with stacks of punchcards.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/naca-computer-operates-an-ibm-telereader-5b6f9f-1024.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Working with a punchcard-based computer in the 1950s (Image: NASA)</em></p>
<p>It used to be that programming even a simple application would require meticulous instructions.</p>
<p>Here are two examples of a "Cesar Cypher", the classic computer science homework project.</p>
<p>This is also known as "ROT-13" because you ROTate the letters by 13 positions. For example, A becomes N (13 letters after A), and B becomes O (13 letters after B).</p>
<p>I'm going to show you two examples of this program.</p>
<p>First, here's the program in x86 Assembly:</p>
<pre><code class="lang-x86">format     ELF     executable 3
entry     start

segment    readable writeable
buf    rb    1

segment    readable executable
start:    mov    eax, 3        ; syscall "read"
    mov    ebx, 0        ; stdin
    mov    ecx, buf    ; buffer for read byte
    mov    edx, 1        ; len (read one byte)
    int    80h

    cmp    eax, 0        ; EOF?
    jz    exit

    xor     eax, eax    ; load read char to eax
    mov    al, [buf]
    cmp    eax, "A"    ; see if it is in ascii a-z or A-Z
    jl    print
    cmp    eax, "z"
    jg    print
    cmp    eax, "Z"
    jle    rotup
    cmp    eax, "a"
    jge    rotlow
    jmp    print

rotup:    sub    eax, "A"-13    ; do rot 13 for A-Z
    cdq
    mov    ebx, 26
    div    ebx
    add    edx, "A"
    jmp    rotend

rotlow:    sub    eax, "a"-13    ; do rot 13 for a-z
    cdq
    mov    ebx, 26
    div    ebx
    add    edx, "a"

rotend:    mov    [buf], dl

print:     mov    eax, 4        ; syscall write
    mov    ebx, 1        ; stdout
    mov    ecx, buf    ; *char
    mov    edx, 1        ; string length
    int    80h

    jmp    start

exit:     mov     eax,1        ; syscall exit
    xor     ebx,ebx        ; exit code
    int     80h
</code></pre>
<p>This x86 Assembly example comes from the Creative Commons-licensed Rosetta Code project.</p>
<p>And here's the same program, written in Python:</p>
<pre><code class="lang-py"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">rot13</span>(<span class="hljs-params">text</span>):</span>
    result = []

    <span class="hljs-keyword">for</span> char <span class="hljs-keyword">in</span> text:
        ascii_value = ord(char)

        <span class="hljs-keyword">if</span> <span class="hljs-string">'A'</span> &lt;= char &lt;= <span class="hljs-string">'Z'</span>:
            result.append(chr((ascii_value - ord(<span class="hljs-string">'A'</span>) + <span class="hljs-number">13</span>) % <span class="hljs-number">26</span> + ord(<span class="hljs-string">'A'</span>)))
        <span class="hljs-keyword">elif</span> <span class="hljs-string">'a'</span> &lt;= char &lt;= <span class="hljs-string">'z'</span>:
            result.append(chr((ascii_value - ord(<span class="hljs-string">'a'</span>) + <span class="hljs-number">13</span>) % <span class="hljs-number">26</span> + ord(<span class="hljs-string">'a'</span>)))
        <span class="hljs-keyword">else</span>:
            result.append(char)

    <span class="hljs-keyword">return</span> <span class="hljs-string">''</span>.join(result)

<span class="hljs-keyword">if</span> __name__ == <span class="hljs-string">"__main__"</span>:
    input_text = input(<span class="hljs-string">"Enter text to be encoded/decoded with ROT-13: "</span>)
    print(<span class="hljs-string">"Encoded/Decoded text:"</span>, rot13(input_text))
</code></pre>
<p>This is quite a bit simpler and easier to read, right? </p>
<p>This Python example comes straight from GPT-4. I prompted it the same way Captain Picard would prompt the ship's computer in Star Trek.</p>
<p>Here's exactly what I said to it: "Computer. New program. Take each letter of the word I say and replace it with the letter that appears 13 positions later in the English alphabet. Then read the result back to me. The word is Banana." </p>
<p>GPT-4 produced this Python code, and then read the result back to me: "Onanan."</p>
<p>What we're doing here is called Declarative Programming. We're declaring "computer, you should do this." And the computer is smart enough to understand our instructions and execute them.</p>
<p>Now, the style of coding most developers use today is Imperative Programming. We're telling the computer exactly what to do, step-by-step. Because historically, computers have been pretty dumb. So we've had to help them put one foot in front of the other.</p>
<p>The field of software development just isn't mature yet. </p>
<p>But just like early human tools advanced – from stone to bronze to iron – the same is happening with software tools. And much faster.</p>
<p>We're probably still in the programming equivalent of the Bronze Age right now. But we may reach the Iron Age in our lifetime. Generative AI tools like GPT are quickly becoming more powerful and more reliable.</p>
<p>The developer community is still divided on how useful tools like GPT will be for software development.</p>
<p>On one side, you have the "become your own boss" entrepreneur influencers who say things like: "You don't need to learn to code anymore. ChatGPT can write all your code for you. You just need an app idea."</p>
<p>And on the other side of the spectrum, you have "old guard" developers with decades of programming experience – many of whom are skeptical that tools like GPT are really all that useful for producing production-grade code.</p>
<p>As with most things, the real answer is probably somewhere in between.</p>
<p>You don't have to look hard to find YouTube videos of people who start with an app idea, then prompt ChatGPT for the code they need. Some people can even take that code and wire it together into an app that works.</p>
<p>Large Language Models like GPT-4 are impressive, and the speed at which they're improving is even more impressive. </p>
<p>Still, many developers are skeptical about how useful these tools will ultimately become. They question whether we'll be able to get AIs to stop "hallucinating" false information.</p>
<p>This is the fundamental problem of "Interpretability." It could be decades before we truly understand what's going on inside of a black box AI like GPT-4. And until we do, we should double check everything it says, and assume there will be lots of bugs and security flaws in the code that it gives us.</p>
<p>There's a big difference from being able to get a computer to do something for you, and actually understanding how the computer is doing it.</p>
<p>Many people can operate a car. But far fewer can repair a car – let alone design a new car from the ground up.</p>
<p>If you want to be able to develop powerful software systems that solve new problems – and you want those systems to be fast and secure – you're still going to need to learn how to code properly.</p>
<p>And that means feeling your way through a lot of ambiguity.</p>
<h3 id="heading-learning-to-code-is-an-ambiguous-process">Learning to Code is an Ambiguous Process</h3>
<p>When you're learning to code, you constantly ask yourself: "Am I spending my time wisely? Am I learning the right tools? Do these book authors / course creators even know what they're talking about?"</p>
<p>Ambiguity fogs your every study session. "Did my test case fail because the tutorial is out of date, and there have been breaking changes to the framework I'm using? Or am I just doing it wrong?"</p>
<p>As I mentioned earlier with Tutorial Hell, you also have to cope with "grass is greener on the other side" disease.</p>
<p>This is compounded by the fact that some developers think it's clever to answer questions with "RTFM" which means "Read the Freaking Manual." Not super helpful. Which manual? Which section?</p>
<p>Another problem is: you don't know what you don't know. Often you can't even articulate the question you're trying to ask.</p>
<p>And if you can't even ask the right question, you're going to thrash.</p>
<p>This is extra hard with coding because it's possible no one has attempted to build quite the same app that you're building.</p>
<p>And thus some of the problems you encounter may be unprecedented. There may be no one to turn to.</p>
<p>15% of the queries people type into Google every day have never ever been searched before. That's bad news if you're the person typing one of those.</p>
<p>My theory is that most developers will figure out how to solve a problem and simply move on, without ever documenting it anywhere. So you may be one of dozens of developers who has had to invent their own solution to the same exact problem.</p>
<p>And then, of course, there are the old forum threads and StackOverflow pages.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/wisdom_of_the_ancients_png__485-270_.png" alt="Image" width="600" height="400" loading="lazy">
<em>Comic by XKCD</em></p>
<h3 id="heading-how-not-to-get-lost-when-learning-to-code">How Not to Get Lost When Learning to Code</h3>
<p>The good news is: both <strong>competence</strong> and <strong>confidence</strong> come with practice.</p>
<p>Soon you'll know exactly what to google. You'll get a second sense for how documentation is usually structured, and where to look for what. And you'll know where to ask which questions.</p>
<p>I wish there were a simpler solution to the ambiguity problem. But you just need to accept it. Learning to code is an ambiguous process. And even experienced developers grapple with ambiguity.</p>
<p>After all, coding is the rare profession where you can just infinitely reuse solutions to problems you've previously encountered.</p>
<p>Thus as a developer, you are always doing something you've never done before.</p>
<p>People think software development is about typing code into a computer. But it's really about learning.</p>
<p>You're going to spend a huge portion of your career just thinking really hard. Or blindly inputting commands into a prompt trying to understand how a system works.</p>
<p>And you're going to spend a lot of time in meetings with other people: managers, customers, fellow devs. Learning about the problem that needs to be solved, so you can build a solution to it.</p>
<p>Get comfortable with ambiguity and you will go far.</p>
<h3 id="heading-learning-to-code-is-one-error-message-after-another">Learning to Code is One Error Message After Another</h3>
<p>A lot of people who are learning to code feel like they hit a wall. Progress does not come as fast as they expect.</p>
<p>One huge reason for this: in programming, the feedback loop is much tighter than in other fields.</p>
<p>In most schools, your teacher will give you assignments, then grade those assignments and give them back to you. Over the course of a semester, you may only have a dozen instances where you get feedback.</p>
<p>"Oh no, I really bombed that exam," you might say to yourself. "I need to study harder for the midterm."</p>
<p>Maybe your teacher will leave notes in red ink on your paper to help you improve your work.</p>
<p>Getting a bad grade on an exam or paper can really ruin your day.</p>
<p>And that's how we generally think about feedback as humans.</p>
<p>If you've spent much time coding, you know that computers are quite fast. They can execute your code within a few milliseconds.</p>
<p>Most of the time your code will crash.</p>
<p>If you're lucky, you'll get an error message.</p>
<p>And if you're really lucky, you'll get a "stack trace" – everything the computer was trying to do when it encountered the error – along with a line number for the piece of code that caused the program to crash.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/oh-my-zsh-stack-trace-error.jpg" alt="A stack trace error message while running freeCodeCamp locally." width="600" height="400" loading="lazy"></p>
<p>Now this in-your-face negative feedback from a computer. Not everyone can handle it seeing this over and over all day long.</p>
<p>Imagine if every time you handed your teacher your term paper, they handed it back with big red "F" written on it. And imagine they did this before you could even blink. Over and over.</p>
<p>That's what coding can feel like sometimes. You want to grab the computer and shout at it, "why don't you just understand what I'm trying to do?"</p>
<h3 id="heading-how-not-to-get-frustrated">How Not to Get Frustrated</h3>
<p>The key, again, is practice.</p>
<p>Over time, you will develop a tolerance for vague error messages and screen-length stack traces.</p>
<p>Coding will never be harder than it is when you're just starting out.</p>
<p>Not only do you not know what you're doing, but you're not used to receiving such impersonal, rapid-fire, negative feedback.</p>
<p>So here are some tips:</p>
<h4 id="heading-tip-1-know-that-you-are-not-uniquely-bad-at-this">Tip #1: Know that you are not uniquely bad at this.</h4>
<p>Everyone who learns to code struggles with the frustration of trying to Vulcan Mind Meld with a computer, and get it to understand you. (That's another Star Trek reference.)</p>
<p>Of course, some people started programming when they were just kids. They may act like they've always been good at programming. But they most likely struggled just like we adults do, and over time have simply forgotten the hours of frustration.</p>
<p>Think of the computer as your friend, not your adversary. It's just asking you to clarify your instructions.</p>
<h4 id="heading-tip-2-breathe">Tip #2: Breathe.</h4>
<p>Many people's natural reaction when they get an error message is to gnash their teeth. Then go back into their code editor and start blindly changing code, hoping to somehow luck into getting past it.</p>
<p>This does not work. And I'll tell you why.</p>
<p>The universe is complex. Software is complex. You are unlikely to just Forest Gump your way into anything good.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/gump.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Forest Gump doing what he does and getting improbably lucky catching shrimp.</em></p>
<p>You may have heard of the Infinite Monkey Theorem. It's a thought experiment where you imagine chimpanzees typing on typewriters.</p>
<p>If you had a newsroom full of chimpanzees doing this, how long would it take before one of them typed out the phrase "to be or not to be" by random chance?</p>
<p>Let's say each chimp types one random character per second. It would likely take 1 quintillion years for one of them to type "to be or not to be." That's 10 to the 18th power. A billion billion.</p>
<p>Even assuming the chimps remain in good health and the typewriters are regularly serviced – the galaxy would be a cold, dark void by the time one of them managed to type "to be or not to be."</p>
<p>Why do I tell you all of this? Because you don't want to be one of those chimps.</p>
<p>In that time, you could almost certainly figure out a way to teach those chimps how to type English words. They could probably manage to type out all of Hamlet – not just its most famous line.</p>
<p>Even if you somehow do get lucky, and get past the bug, what will you have learned? </p>
<p>So instead of thrashing, you want to take some time. Understand the code. Understand what's happening. And then fix the error.</p>
<p>Always take time to understand the failing code. Don't be a quintillionarian chimp. (I think that means someone who is 1 quintillion years old, though according to Google, nobody has ever typed that word before.)</p>
<p>Instead of blindly trying things, hoping to get past the error message, slow down.</p>
<p>Take a deep breath. Stretch. Get up to grab a hot beverage.</p>
<p>Your future self will be grateful that you took this as a teachable moment.</p>
<h4 id="heading-tip-3-use-rubber-duck-debugging">Tip #3: Use Rubber Duck Debugging</h4>
<p>Get a rubber ducky and set it next to your computer. Every time you hit an error message, try to explain what you think is happening to your rubber duck.</p>
<p>Of course, this is silly. How could this possibly be helpful?</p>
<p>Except it is.</p>
<p>Rubber Duck Debugging is a great tool for slowing down and talking through the problem at hand.</p>
<p>You don't have to use a rubber duck, of course. You could explain your Python app to your pet cactus. Your SQL query to the cat that keeps jumping onto your keyboard.</p>
<p>The very act of explaining your thinking out loud seems to help you process the situation better.</p>
<h3 id="heading-how-do-most-people-learn-to-code">How do Most People Learn to Code?</h3>
<p>Now let's talk about traditional pathways to a first developer job.</p>
<p>Why should you care what everyone else does? Spoiler alert: you don't really need to.</p>
<p>You do <strong>you</strong>.</p>
<p>This said, you may doubt yourself and the decisions you've made about your learning. You may yearn for the path not taken.</p>
<p>My goal with this section is to calm any anxieties you may have.</p>
<h4 id="heading-the-importance-of-computer-science-degrees">The Importance of Computer Science Degrees</h4>
<p>University degrees are still the gold standard for preparing for a career in software development. Especially bachelor's degrees in Computer Science.</p>
<p>Before you start saying "But I don't have a computer science degree" – no worries. <strong>You don't need a Computer Science degree to become a developer</strong>.</p>
<p>But their usefulness is undeniable. And I'll explain why.</p>
<p>First, you may wonder: why should developers study computer science? After all, one of the most prominent developers of all time had this to say about the field:</p>
<blockquote>
<p>"Computer science education cannot make anybody an expert programmer any more than studying brushes and pigment can make somebody an expert painter." – Eric Raymond, Developer, Computer Scientist, and Author</p>
</blockquote>
<p>Computer Science departments were traditionally part of the math department. Universities back in the 1960s and 1970s didn't know quite where to put this whole computer thing.</p>
<p>At other universities, Computer Science was considered an extension of Electrical Engineering. And until recently, even University of California – Berkeley – one of the greatest public universities in the world – only provided Computer Science degrees as sort of a double-major with Electrical Engineering.</p>
<p>But most universities have now come to understand the importance of Computer Science as a field of study.</p>
<p>As of writing this, Computer Science is the highest paying degree you can get. Higher even than fields focused on money, such as Finance and Economics.</p>
<p><a target="_blank" href="https://www.glassdoor.com/blog/50-highest-paying-college-majors/">According to Glassdoor</a>, the average US-based Computer Science major makes more money at their first job than any other major. US $70,000. That's a lot of money for someone who just graduated from college.</p>
<p>More than Nursing majors ($59,000), Finance majors ($55,000) and Architecture majors ($50,000).</p>
<p>OK – so getting a Computer Science degree can help you land a high-paying entry-level job. That is probably news to no one. But why is that?</p>
<h4 id="heading-how-employers-think-about-bachelors-degrees">How Employers Think About Bachelor's Degrees</h4>
<p>You may have heard some big employers in tech say things like, "we no longer require job candidates to have a bachelor's degree."</p>
<p>Google said this. Apple said this.</p>
<p>And I believe them. That they no longer require bachelor's degrees.</p>
<p>We've had lots of freeCodeCamp alumni get jobs at these companies, some of whom did not have a bachelor's degrees.</p>
<p>But those freeCodeCamp alumni who landed those jobs probably had to be extra strong candidates to overcome the fact that they didn't have bachelor's degrees.</p>
<p>You can look at these job openings as having a variety of criteria they judge candidates on:</p>
<ol>
<li>Work experience</li>
<li>Education</li>
<li>Portfolio and projects</li>
<li>Do they have a recommendation from someone who already works at the company? (We'll discuss building your network in depth in Chapter 2)</li>
<li>Other reputation considerations (we'll discuss building your reputation in Chapter 3)</li>
</ol>
<p>For these employers who do not require a bachelor's degree, education is just one of several considerations. If you are stronger in other areas, they may opt to interview you – regardless of whether you've ever even set foot inside a university classroom.</p>
<p>Just note that having a bachelor's degree will make it easier for you to get an interview, even at these "degree-optional" employers.</p>
<h4 id="heading-why-do-so-many-developer-jobs-require-a-computer-science-degree-specifically">Why do so Many Developer Jobs Require a Computer Science Degree Specifically?</h4>
<p>A bachelor's is a bachelor's, I often tell people. Because for most intents and purposes, it is.</p>
<p>Want to enter the US military as an officer, rather than an enlisted service member? You'll need a bachelor's degree, but any major will do.</p>
<p>Want to get a work visa to work abroad? You'll probably need a bachelor's degree, but any major will do.</p>
<p>And for so many job openings that say "bachelor's degree required" – any major will do.</p>
<p>Why is this? Doesn't the subject you study in university matter at all?</p>
<p>Well, here's my theory on this: what you learn in university is less important than <strong>whether</strong> you finished university.</p>
<p>Employers are trying to select for people who can figure out a way to get through this rite of passage.</p>
<p>It is certainly true that you can be at the bottom of your class, repeating courses you failed, and being on academic probation for half the time. But a degree is a degree.</p>
<p>You know what they call the student who finished last in their class at medical school? "Doctor."</p>
<p>And for most employers, the same holds true.</p>
<p>In many cases, HR folks are just checking a box on their job application filtering software. They're filtering out applicants who don't have a degree. In those cases, they may never even look at job applications from people without degrees.</p>
<p>Again, not every employer is like this. But many of them are. Here in the US, and perhaps even more so in other countries.</p>
<p>It sucks, but it's how the labor market works right now. It may change over the next few decades. It may not.</p>
<p>This is why I always encourage people who are in their teens and 20s to seriously considering getting a bachelor's degree.</p>
<p>Not because of any of the things universities market themselves as:</p>
<ul>
<li>The education itself. (You can take courses from some of the best universities online for free, so this alone does not justify the high cost of tuition.)</li>
<li>The "college experience" of living in a dorm, making new friends, and self discovery. (Most US University students never live on campus so they don't really get this anyway.)</li>
<li>General education courses that help you become a "well rounded individual" (Ever hear of the Freshman 15? This is a joke of course. But a lot of university freshman do gain weight due to the stress of the experience.)</li>
</ul>
<p>Again, the real value of getting a bachelor's degree – the real reason Americans pay $100,000 or more for 4 years of university – is because many employers require degrees.</p>
<p>Of course, there are other benefits of having a bachelor's degree, such as the ones I mentioned: expanded military career options, and greater ease getting work visas.</p>
<p>One of these is: if you want to become a doctor, dentist, lawyer, or professor, you will first need a bachelor's degree. You can then use that to get into grad school.</p>
<p>OK – this is a lot of background information. So allow me to answer your questions bluntly.</p>
<h3 id="heading-do-you-need-a-university-degree-to-work-as-a-software-developer">Do You Need a University Degree to Work as a Software Developer?</h3>
<p>No. There are plenty of employers who will hire you without a bachelor's degree.</p>
<p>A bachelor's degree will make it much easier to get an interview at a lot of employers. And it may also help you command a higher salary.</p>
<h3 id="heading-what-about-associates-degrees-are-those-valuable">What About Associate's Degrees? Are Those Valuable?</h3>
<p>In theory, yes. There are some fields in tech where having an associates may be required. And I think it always does increase your chances of getting an interview.</p>
<p>This said, I would not recommend going to university with the specific goal of getting an associate's degree. I would 100% encourage you to stay in school until you get a bachelor's degree, which is vastly more useful.</p>
<p>According to the US Department of Education, over the course of your career, having a bachelor's degree will earn you 31% more than merely having an associate's degree.</p>
<p>And I'm confident that difference is much wider with a bachelor's in Computer Science.</p>
<h3 id="heading-is-it-worth-going-to-university-to-get-a-bachelors-degree-later-in-life-if-you-dont-already-have-one">Is it Worth Going to University to Get a Bachelor's Degree Later in Life, if You Don't Already Have One?</h3>
<p>Let's say you're in your 30s. Maybe you attended some college or university courses. Maybe you completed the first two years and were able to get an associate's degree.</p>
<p>Does it make sense to go "back to school" in the formal sense?</p>
<p>Yes, it may make sense to do so.</p>
<p>But I don't think it ever makes sense to quit your job to go back to school full time.</p>
<p>The full-time student lifestyle is really designed with "traditional" students in mind. That is, people age 18 to 22 (or a bit older if they served in the military), who have not yet entered the workforce beyond high school / summer jobs.</p>
<p>Traditional universities cost a lot of money to attend, and the assumption is that students will pay through some combination of scholarships, family funds, and student loans.</p>
<p>As a working adult, you'll have less access to these funding sources. And just as importantly, you'll have less time on your hands than a recent high school graduate would.</p>
<p>But that doesn't mean you have to give up on the dream of getting a bachelor's degree.</p>
<p>Instead of attending a traditional university, I recommend that folks over 30 attend one of the online nonprofit universities. Two that have good reputations, and whose fees are quite reasonable, are Western Governor's University and University of the People.</p>
<p>You may also find a local community college or state university extension program that offers degrees. Many of these programs are online. And some of them are even self-paced, so that you can complete courses as your work schedule permits.</p>
<p>Do your research. If a school looks promising, I recommend finding one of its alumni on LinkedIn and reaching out to them. Ask them questions about their experience, and whether they think it was worth it.</p>
<p>I recommend not taking on any debt to finance your degree. It is much better to attend a cheaper school. After all, a degree is a degree. As long as it's from an accredited institution, it should be fine for most intents and purposes.</p>
<h3 id="heading-if-you-already-have-a-bachelors-degree-does-it-make-sense-to-go-back-and-earn-a-second-bachelors-in-computer-science">If You Already Have a Bachelor's Degree, Does it Make Sense to Go Back and Earn a Second Bachelor's in Computer Science?</h3>
<p>No. Second bachelor's degrees are almost never worth the time and money.</p>
<p>If you have any bachelor's degree – even if it's in a non-STEM field – you have already gotten most of the value you will get out of university.</p>
<h3 id="heading-what-about-a-masters-of-computer-science-degree">What About a Master's of Computer Science Degree?</h3>
<p>These can be helpful for career advancement. But you should pursue them later, after you're already working as a developer.</p>
<p>Many employers will pay for their employee's continuing education.</p>
<p>One program a lot of my friends in tech have attended is Georgia Tech's Master's in Computer Science degree.</p>
<p>Georgia Tech's Computer Science department is among the best in the US. And this degree program is not only fully online – it's also quite affordable.</p>
<p>But I wouldn't recommend doing it now. First focus on getting a developer job. (We'll cover that in-depth later in this book).</p>
<h3 id="heading-will-degrees-continue-to-matter-in-the-future">Will Degrees Continue to Matter in the Future?</h3>
<p>Yes, I believe that university degrees will continue to matter for decades – and possibly centuries – to come.</p>
<p>University degrees have existed for more than 1,000 years.</p>
<p>Many of the top universities in the US are older than the USA itself is. (Harvard is more than 400 years old.)</p>
<p>The death of the university degree is greatly exaggerated.</p>
<p>It has become popular in some circles to bash universities, and say that degrees don't matter anymore.</p>
<p>But if you look at the statistics, this is clearly not true. They do have an impact on lifetime earnings.</p>
<p>And just as importantly, they can open up careers that are safer, more stable, and ultimately more fulfilling.</p>
<p>Sure, you can make excellent money working as a deckhand offshore, servicing oil rigs.</p>
<p>But you can make similarly excellent money working as a developer in a climate-controlled office, servicing servers and patching codebases.</p>
<p>One of these jobs is dangerous, back-breaking work. The other is a job you could comfortably do for 40 years.</p>
<p>Many of the "thought leaders" out there who are bashing universities have themselves benefitted from a university education.</p>
<p>One reason why I think so many people think degrees are "useless" is: it's hard to untangle the learning from the status boost you get.</p>
<p>Is university just a form of class signaling – a way for the wealthy to continue to pass advantage on to their children? After all, you're 3 times as likely to find a rich kid at Harvard as you are a poor kid.</p>
<p>The fact is: life is fundamentally unfair. But that does not change how the labor market works.</p>
<p>You can choose easy mode, and finish a degree that will give you more options down the road.</p>
<p>Or you can go hard mode, potentially save time and money, and just be more selective about which employers you apply to.</p>
<p>I have plenty of friends who've used both approaches to great success.</p>
<h3 id="heading-what-alternatives-are-there-to-a-university-degree">What Alternatives are There to a University Degree?</h3>
<p>I've worked in adult education for nearly two decades, and I have yet to see a convincing substitute for a university degree.</p>
<p>Sure – there are certification programs and bootcamps.</p>
<p>But these do not carry the same weight with employers. And they are rarely as rigorous.</p>
<p><em>Side note: when I say "certification programs" I mean a program where you attend a course, then earn a certification at the end. These are of limited value. But exam-based certifications from companies like Amazon and Microsoft are quite valuable. We'll discuss these in more depth later.</em></p>
<p>What I tell people is: to degree or not to degree – that is the question.</p>
<p>I meet lots of people who are auto mechanics, electricians, or who do some other sort of trade, who don't have a bachelor's. They can clearly learn a skillset, apply it, and hold down a job.</p>
<p>I meet lots of people who are bookkeepers, paralegals, and other "knowledge workers" who don't have a bachelor's. They can clearly learn a skillset, apply it, and hold down a job.</p>
<p>In many cases, these people can just learn to code on their own, using free learning resources and hanging out with likeminded people.</p>
<p>Some of these people have always had the personal goal of going back and finishing their bachelor's. That's a good reason to do it.</p>
<p>But it's not for everyone.</p>
<p>If you want formal education, go for the bachelor's degree. If you don't want formal education, don't do any program. Just self-teach.</p>
<p>The main thing bootcamps and other certification programs are going to give you is structure and a little bit of peer pressure. That's not a bad thing. But is it worth paying thousands of dollars for it?</p>
<h3 id="heading-how-to-teach-yourself-to-code">How to Teach Yourself to Code</h3>
<p>Most developers are self-taught. Even the developers who earned a Bachelor's of computer science still often report themselves as "self-taught" on industry surveys like Stack Overflow's annual survey.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/stack-overflow.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Most working developers consider themselves to be "self-taught" (Image: Stack Overflow 2016 Survey)</em></p>
<p>This is because learning to code is a life-long process. There are constantly new tools to learn, new legacy codebases to map out, and new problems to solve.</p>
<p>So whether you pursue formal education or not, know this: you will need to get good at self-teaching.</p>
<h4 id="heading-what-does-it-mean-to-be-a-self-taught-developer">What Does it Mean to be a "Self-Taught" Developer?</h4>
<p>Not to be pedantic, but when I refer to self-teaching, I mean self-directed learning – learning outside of formal education.</p>
<p>Very few people are truly "self-taught" at anything. For example, Isaac Newton taught himself Calculus because there were no Calculus books. He had to figure it out and invent it as he went along.</p>
<p>Similarly, Ada Lovelace taught herself programming. Because before her there was no programming. She invented it.</p>
<p>Someone might tell you: "You're not really self taught because you learned from books or online courses. So you had teachers." And they are correct, but only in the most narrow sense.</p>
<p>If someone takes issue with you calling yourself self-taught, just say: "By your standards, no one who wasn't raised by wolves can claim to be self-taught at anything."</p>
<p>Point them to this section of this book and tell them: "Quincy anticipated your snobbery." And then move on with your life.</p>
<p>Because come on, life's too short, right?</p>
<p>You're self taught.</p>
<h4 id="heading-what-is-self-directed-learning">What is Self-Directed Learning?</h4>
<p>As a self-learner, you are going to curate your own learning resources. You're going to choose what to learn, from where. That is the essence of "Self-Directed Learning."</p>
<p>But how do you know you're learning the right skills, and leveraging the right resources?</p>
<p>Well, that's where community comes in.</p>
<p>There are lots of communities of learners around the world, all helping one another expand their skills.</p>
<p>Community is a hard word to define. Is Tech Twitter a community? What about the freeCodeCamp forum? Or the many Discord groups and subreddits dedicated to specific coding skillsets?</p>
<p>I consider all of these communities. If there are people who regularly hang out there and help one another, I consider it a community.</p>
<p>What about in-person events? The monthly meetup of Ruby developers in Oakland? The New York City Startup community meetup? The Central Texas Linux User Group?</p>
<p>These communities can be online, in-person, or some mix of both.</p>
<p>We'll talk more about communities in the Build Your Network chapter. But the big takeaway is: the new friends you meet in these communities can help you narrow your options for what to learn, and which resources to learn from.</p>
<h3 id="heading-what-programming-language-should-i-learn-first">What Programming Language Should I Learn First?</h3>
<p>The short answer is: it doesn't really matter. Once you've learned one programming language well, it is much easier to learn your second language.</p>
<p>There are different types of programming languages, but today most development is done using "high-level scripting languages" like JavaScript and Python. These languages trade away the raw efficiency you get from "low-level programming languages" like C. What they get in return: the benefit of being much easier to use.</p>
<p>Today's computers are billions of times faster than they were in the 1970s and 1980s, when people were writing most of their programs in languages like C. That power more than makes up for the relative inefficiency of scripting languages.</p>
<p>It's worth noting that both JavaScript and Python themselves are written in C, and they are both getting faster every year – thanks to their large communities of open source code contributors.</p>
<p>Python is a powerful language for scientific computing (Data Science and Machine Learning).</p>
<p>And JavaScript... well, JavaScript can do everything. It is the ultimate Swiss Army Knife programming language. JavaScript is the duct tape that holds the World Wide Web together.</p>
<blockquote>
<p>"Any application that can be written in JavaScript, will eventually be written in JavaScript." – Atwood's Law (Jeff Atwood, founder of Stack Overflow and Discourse)</p>
</blockquote>
<p>You could code your entire career in JavaScript and would never need to learn a second language. (This said, you'll want to learn Python later on, and maybe some other languages as well.)</p>
<p>So I recommend starting with JavaScript. Not only is it much easier to use than languages like Java and C++ – it's easier to learn, too. And there are far, far more job openings for people who know JavaScript.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/Find_Javascript_Jobs_with_great_pay_and_benefits_in_United_States___Indeed_com_--.png" alt="Image" width="600" height="400" loading="lazy">
<em>A screenshot from job search engine Indeed. My search for "javascript" for the US yielded 68,838 job listings.</em></p>
<p>The other skills you'll want to focus on are <strong>HTML</strong> and <strong>CSS</strong>. If a webpage were a body, HTML would be the bones, and CSS would be the skin. (JavaScript would be the muscles, making it possible for the website to move around and be interactive.)</p>
<p>You can learn some HTML and CSS in a single afternoon. Like most of the tools I mention here, they are easy to learn, but difficult to master.</p>
<p>You'll also want to learn how to use <strong>Linux</strong>. Linux powers a vast majority of the world's servers, and you will spend much of your career running commands in the Linux command line.</p>
<p>If you have a Mac, MacOS has a terminal that accepts almost all the same commands as Linux. (MacOS and Linux have a common ancestor in Unix.)</p>
<p>But if you're on a Windows PC, you'll want to install WSL, which stands for Windows Subsystem for Linux. You will then be able to run Linux commands on your PC. And if you're feeling adventurous, you can even dual boot both the Windows and Linux operating systems on the same computer.</p>
<p>If you're going to install Linux on a computer, I recommend starting with Ubuntu. It is the most widely used (and widely documented) Linux distribution. So it should be the most forgiving.</p>
<p>Make no mistake – Linux is quite a bit harder to use than Windows and MacOS. But what you get in return for your efforts is an extremely fast, secure, and highly customizable operating system.</p>
<p>Also, you will never have to pay for an operating system license again. Unless you want to. Red Hat is a billion dollar company even though its software is open source, because companies pay for their help servicing and supporting Linux servers.</p>
<p>You'll also want to learn <strong>Git</strong>. This Version Control System is how teams of developers coordinate their changes to a codebase.</p>
<p>You may have heard of GitHub. It's a website that makes it easier for developers to collaborate on open source projects. And it further extends some of the features of Git. You'll learn more about GitHub in the How to Build Your Reputation chapter later.</p>
<p>You'll want to learn <strong>SQL</strong> and how relational databases work. These are the workhorses of the information economy. </p>
<p>You'll also hear a lot about NoSQL databases (Non-relational databases such as graph databases, document databases, and key-value stores.) You can learn more about these later. But focus on SQL first.</p>
<p>Finally, you'll want to learn how <strong>web servers</strong> work. You'll want to start with Node.js and Express.js.</p>
<p>When you hear the term "full stack development" it refers to tying together the front end (HTML, CSS, JavaScript) with the back end (Linux, SQL databases, and Node + Express).</p>
<p>There are lots of other tools you'll want to learn, like React, NGINX, Docker, and testing libraries. You can pick these up as you go.</p>
<p>But the key skills you should spend 90% of your pre-job learning time on are:</p>
<ol>
<li>HTML</li>
<li>CSS</li>
<li>JavaScript</li>
<li>Linux</li>
<li>Git</li>
<li>SQL</li>
<li>Node.js</li>
<li>Express.js</li>
</ol>
<p>If you learn these tools, you can build most major web and mobile apps. And you will be qualified for most entry-level developer jobs. (Of course, many job descriptions will include other tools, but we'll discuss these later in the book.)</p>
<p>So you may be thinking: great. How do I learn these?</p>
<h3 id="heading-where-do-i-learn-how-to-code">Where do I learn how to code?</h3>
<p>Funny you should ask. There's a full curriculum designed by experienced software engineers and teachers. It's designed with busy adults in mind. And it's completely free and self-paced.</p>
<p>That's right. I'm talking about the <a target="_blank" href="https://www.freecodecamp.org/learn">freeCodeCamp core curriculum</a>. It will help you learn:</p>
<ul>
<li>Front End Development</li>
<li>Back End Development</li>
<li>Engineering Mathematics</li>
<li>and Scientific Computing (with Python for Data Science and Machine Learning)</li>
</ul>
<p>To date, thousands of people have gone through this core curriculum and gotten a developer job. They didn't need to quit their day job, take out loans, or really risk anything other than some of their nights and weekends.</p>
<p>In practice, freeCodeCamp has become the default path for most people who are learning to code on their own.</p>
<p>If nothing else, the freeCodeCamp core curriculum can be your "home base" for learning, and you can branch out from there. You can learn the core skills that most jobs require, and also dabble in technologies you're interested in.</p>
<p>There are decades worth of books and courses to learn from. Some are available at your public library, or through monthly subscription services. (And you may be able to access some of these subscription services for free through your library as well.)</p>
<p>Also, freeCodeCamp now has nearly 1,000 free full-length courses on everything from AWS certification prep to mobile app development to Kali Linux.</p>
<p>There has never been an easier time to teach yourself programming.</p>
<h3 id="heading-building-your-skills-is-a-life-long-endeavor">Building Your Skills is a Life-Long Endeavor</h3>
<p>We've talked about why self-teaching is probably the best way to go, and how to go about it.</p>
<p>We've talked about the alternatives to self-teaching, such as getting a bachelor's degree in Computer Science, or getting a Master's degree.</p>
<p>And we've talked about which specific tools you should focus on learning first.</p>
<p>Now, let's shift gears and talk about how to build the second leg of your stool: your network.</p>
<h2 id="heading-chapter-2-how-to-build-your-network">Chapter 2: How to Build Your Network</h2>
<blockquote>
<p>"If you want to go fast, go alone. If you want to go far, go together." – African Proverb</p>
</blockquote>
<p>"Networking." You may wince at the sound of that word.</p>
<p>Networking may bring to mind awkward job fairs in stuffy suits, desperately pushing your résumé into the hands of anyone who will accept it.</p>
<p>Networking may bring to mind alcohol-drenched watch parties – where you pretend to be interested in a sport you don't even follow.</p>
<p>Networking may bring to mind wishing "happy birthday" to people you barely know on LinkedIn, or liking their status updates hoping they'll notice you.</p>
<p>But networking does not have to be that way.</p>
<p>In this chapter, I'll tell you everything I've learned about meeting people. I'll show you how to earn their trust and be top of their mind when they're looking for help.</p>
<p>Because at the end of the day, that's what it's all about. Helping people solve their problems. Being of use to people.</p>
<p>I'll show you how to build a robust personal network that will support you for decades to come.</p>
<h3 id="heading-story-time-how-did-a-teacher-in-his-30s-build-a-network-in-tech">Story Time: How did a Teacher in his 30s Build a Network in Tech?</h3>
<p><em>Last time on Story Time: Quincy learned some coding by reading books, watching free online courses, and hanging out with developers at the local Hackerspace. He had just finished building his first project and given his first tech talk...</em></p>
<p>OK – so I now had some rudimentary coding skills. I could now code my way out of the proverbial paper bag.</p>
<p>What was next? After all, I was a total tech outsider.</p>
<p>Well, even though I was new to tech, I wasn't new to working. I'd put food on the table for nearly a decade by working at schools and teaching English.</p>
<p>As a teacher, I got paid to sling knowledge. And as a developer, I'd get paid to sling code.</p>
<p>I already knew one very important truth about the nature of work: it's who you know.</p>
<p>I knew the power of networks. I knew that the path to opportunity goes right through the gatekeepers.</p>
<p>All that stood between me and a lucrative developer job was a hiring manager who could say: "Yes. This Quincy guy seems like someone worthy of joining our team."</p>
<p>Of course, being a tech outsider, I didn't know the culture.</p>
<p>Academic culture is much more formal.</p>
<p>You wear a suit.</p>
<p>You use fancy academic terminology to demonstrate you're part of the "in group."</p>
<p>You find ways to work into every conversation that you went to X university, or that you TA'd under Dr. Y, or that you got published in The Journal of Z.</p>
<p>Career progressions are different. Conferences are different. Power structures are different.</p>
<p>And I didn't immediately appreciate this fact.</p>
<p>The first few tech events I went to, I wore a suit.</p>
<p>I kept neatly-folded copies of my résumé in my pocket at all times.</p>
<p>I even carried business cards. I had ordered sheets of anodized aluminum, and used a laser cutter to etch in my name, email address, and even a quote from legendary educator John Dewey:</p>
<blockquote>
<p>"Anyone who has begun to think places some portion of the world in jeopardy." – John Dewey</p>
</blockquote>
<p>It's still my favorite quote to this day.</p>
<p>But talk about heavy-handed.</p>
<p>"Hi, I'm Quincy. Here's my red aluminum business card. Sorry in advance – it might set off the metal detector on your flight home."</p>
<p>I was trying too hard. And it was probably painfully apparent to everyone I talked to.</p>
<p>I went on Meetup.com and RSVP'd for every developer event I could find. Santa Barbara is a small town, but it's near Los Angeles. So I made the drive for events there, too.</p>
<p>I quickly wised up, and traded my suit for jeans and a hoody. And I noticed that no one else gave out business cards. So I stopped carrying them.</p>
<p>I took cues from the devs I met at the hackerspace: Be passionate, but understated. Keep some of your enthusiasm in reserve.</p>
<p>And I read lots of books to better understand developer culture. </p>
<p><a target="_blank" href="https://www.amazon.com/Coders-Work-Reflections-Craft-Programming/dp/B092R8RQM3?crid=13BTAQ7TH9YSN&amp;linkCode=ll1&amp;tag=out0b4b-20&amp;linkId=32d14a148c54f36f5ef701578a2abd8e&amp;language=en_US&amp;ref_=as_li_ss_tl">The Coders at Work</a> is a good book from the 1980s.</p>
<p><a target="_blank" href="https://www.amazon.com/Hackers-Computer-Revolution-Steven-Levy/dp/1449388396?&amp;linkCode=ll1&amp;tag=out0b4b-20&amp;linkId=0c216f2cd4cc2d2090b8c9b50b0befee&amp;language=en_US&amp;ref_=as_li_ss_tl">Hackers: Heroes of the Revolution</a> is a good book from the 1990s.</p>
<p>For a more contemporary cultural resource, check out the TV series <a target="_blank" href="https://www.amazon.com/Mr-Robot-Complete-Rami-Malek/dp/B0833WXXL6?crid=188UUOE6ZT0W3&amp;keywords=mr+robot&amp;qid=1673746625&amp;sprefix=mr+robot%2Caps%2C111&amp;sr=8-6&amp;linkCode=ll1&amp;tag=out0b4b-20&amp;linkId=a896ab7630fadc332c2696d3a4b8e85d&amp;language=en_US&amp;ref_=as_li_ss_tl">Mr. Robot</a>. Its characters are a bit extreme, but they do a good job of capturing the mindset and mannerisms of many developers.</p>
<p>Soon, I was talking less like a teacher and more like a developer. I didn't stick out quite as awkwardly.</p>
<p>Several times a week I attended local tech-related events. My favorite event wasn't even a developer event. It was the Santa Barbara Startup Night. Once every few weeks, they'd have an event where developers would pitch their prototypes. Some of the devs demoing their code were even able to secure funding from angels – rich people who invest in early-stage companies.</p>
<p>The guy who ran the event was named Mike. He must have known every developer and entrepreneur in Santa Barbara. </p>
<p>When I finally got the nerve to introduce myself to Mike, I was star-struck. He was an ultra-marathoner with a resting heartbeat in the low 40s. Perfectly cropped hair and beard. To me he was the coolest guy on the planet. Always polished. Always respectful.</p>
<p>Mike was "non-technical". He worked as a product manager. And though he knew a lot about technology and user experience design, he didn't know how to code.</p>
<p>Sometimes devs would write non-technical people off. "He's just a business guy," they'd say. Or: "She's a suit." But I never heard anyone say that about Mike. He had the respect of everyone.</p>
<p>I made a point to watch the way Mike interacted with developers. After all, I wasn't that far removed from "non-technical" myself. I'd only been coding for a few months.</p>
<p>Often my old habits would creep in. During conversations I'd have the temptation to show off what I'd learned or what I'd built.</p>
<p>Many developers are modest about their skills or accomplishments. They might say: "I dabble in Python." And little 'ol insecure me would open his big mouth and say something like, "Oh yeah. I've coded so many algorithms in Python. I write Python in my sleep."</p>
<p>And then I'd go home and google that developer's name, and realize they were a core contributor to a major Python library. And I'd kick myself.</p>
<p>I quickly learned not to boast of my accomplishments or my skills. There's a good chance a person you're talking to can code circles around you. But most of them would never volunteer this fact.</p>
<p>There's nothing worse than confidently pulling out your laptop, showing off your code, and then having someone ask you a bunch of questions that you're wholly unprepared to answer.</p>
<p>My first few months of attending events was a humbling experience. But these events energized me to keep pushing forward with my skills.</p>
<p>Soon people around southern California would start to recognize me. They'd say: "I keep running to you at these events. What's your name again?"</p>
<p>One night a dev said, "Let's follow each other on Twitter." I had grudgingly set up a Twitter account a few days earlier, thinking it was a gimmicky website. How much could you really convey with just 140 characters? I had barely tweeted anything. But I did have a Twitter account ready, and she did follow me.</p>
<p>That inspired me to spend more time refining my online presence. I made my LinkedIn less formal and more friendly. I looked at how other devs in the community presented themselves online.</p>
<p>Within a few months, I knew people from so many fields:</p>
<ul>
<li>experienced developers</li>
<li>non-technical or semi-technical people who worked at tech companies</li>
<li>hiring managers and recruiters</li>
<li>and most importantly, my peers who were also mid-career and trying to break into tech</li>
</ul>
<p>Why were peers the most important? Surely they would be the least able to help me get a job, right?</p>
<p>Well, let me tell you a secret: let's say a hiring manager brings on a new dev, trains them, and they turn out to be really good at their job. That hiring manager is going to ask: where can I find more people like you?</p>
<p>Your peers are one of the most important pieces of your network. So many of my freelance opportunities and job interview opportunities came from people who started learning to code around the same time as I did.</p>
<p>We came up together. We were brothers and sisters in arms. Those bonds are the tightest.</p>
<p>Anyway, all this networking over the months would ultimately come to fruition one night when I walked into the bar of a fancy downtown hotel for a developer event.</p>
<p>But more on that in the next chapter. Now let's talk more about the art and science of building your network.</p>
<h3 id="heading-is-it-really-who-you-know">Is it Really Who You Know?</h3>
<p>You may have heard the expression that success is "less about what you know, and more about who you know."</p>
<p>In practice, it's about both.</p>
<p>Yes – your connections may help you land your dream job. But if you're out of your depth, and lack the skills to succeed, you will not fare well in that role.</p>
<p>But let's assume that you are proactively building your skills. You've followed my advice from Chapter 1. When is the right time to start building your network?</p>
<p>The best time to start building your network is <strong>yesterday</strong>.</p>
<p>But you don't need a time machine to do this. Because you already have a network. It's probably much smaller than you'd like it to be, but you <strong>do</strong> know people.</p>
<p>They may be friends from your home town, or the colleagues of your parents. Any person you know from your past – however marginally – may be of help.</p>
<p>So step one is to take full inventory of the people you know. Don't worry – I am not asking you to reach out to anyone yet, or tax your personal relationships.</p>
<p>Think before you move. Formulate a strategy.</p>
<p>First, let's inventory all the people you know.</p>
<h3 id="heading-how-to-build-a-personal-network-board">How to Build a Personal Network Board</h3>
<p>You want to start by creating a list of people you know.</p>
<p>You could do this with a spreadsheet, or a Customer Relationship Management tool (CRM) like sales people use. But that's probably overkill for what we're doing here.</p>
<p>I recommend using a Kanban board tool like Trello, which is free.</p>
<p>You're going to create 5 columns: "to evaluate", "to contact", "waiting for reply", "recently in contact", and "don't contact yet".</p>
<p>Then you're going to want to create labels, so you can classify people by how you know them. Here are some label ideas for you: "Childhood friend", "Friend of the family", "Former colleague", "Classmate", "Friends from Tech Events".</p>
<p>Now you can start creating cards. Each card can just be their name, and if you have time you can add a photo to the card.</p>
<p>Here is the Trello board I created to give you an idea of what this Personal Network Board might look like. I used characters from my favorite childhood movie, the 1989 classic Teenage Mutant Ninja Turtles.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/Personal_Network_Board___Trello_--.png" alt="Image" width="600" height="400" loading="lazy">
<em>My Personal Network Board with my friends from my side job fighting crime.</em></p>
<p>You can go through your social media accounts – even your old school year books if you have them – and start adding people.</p>
<p>Many of these people are not going to be of any help. But I recommend adding them for the sake of being comprehensive. You never know when you'll remember: "oh – so and so got a job at XYZ corp. I should reach out to them."</p>
<p>This process may take a day or two. But know that this is an investment. You'll be able to use this board for the rest of your career.</p>
<p>You may think "I don't need to do this – I already have a LinkedIn account." That might work OK, but LinkedIn is a blunt instrument. You want to maximize signal and minimize noise here. That's why I'm encouraging you to create this dedicated personal network board.</p>
<p>As you add people to your board, you can label them. Take a moment to research each of these people. What are they up to these days? Do they have a job? Run a company?</p>
<p>You can add notes to each card, as you discover new facts about them. Did they recently run a fundraiser 5K run? Did their grandma recently celebrate her 90th birthday? These facts may seem extraneous. But if the person is sharing them on social media, it means these facts are important to <strong>them</strong>.</p>
<p>Make an effort to be interested in people. Their daily lives. Their aspirations. By understanding their motivations and goals, you will have deeper insight into how you can help them.</p>
<p>And as I said earlier, the best way to forge alliances is to help people. We'll talk about this at length in a little bit.</p>
<p>For each of the people you add to your Personal Network Board, consider whether they might be worth reaching out to. Then either put them into the "to contact" or "don't contact yet" column.</p>
<p>You may be wondering: why is the column called "don't contact <strong>yet</strong>"? Because you never know when it might be helpful to know someone. Never take any friendship or acquaintanceship for granted.</p>
<p>Once you've filled up your board, labeled everyone, and sorted them into columns, you're ready to start reaching out.</p>
<h3 id="heading-how-to-prepare-for-network-outreach">How to Prepare for Network Outreach</h3>
<p>The main thing to keep in mind when reaching out and trying to make an impression: keep yourself simple.</p>
<p>People are busy, and they can only remember so many facts about you. You want to boil down who you are to the fundamentals. And the best way to do this is to write a personal bio.</p>
<h4 id="heading-how-to-write-a-personal-bio-for-social-media">How to Write a Personal Bio for Social Media</h4>
<p>You want your presence to be consistent across all of your social media accounts.</p>
<p>Here's how I introduce myself:</p>
<p>"I'm Quincy. I'm a teacher at freeCodeCamp. I live in Dallas, Texas. I can help you learn to code."</p>
<p>Go ahead and write yours. See if you can get it down to 100 characters or less. Try to avoid using fancy words or jargon.</p>
<p>It may be hard to distill your identity down to a few words. But this is an important process.</p>
<p>Remember: people are busy. They don't need to know your life story. As you get to know these people better, you can gradually fill in the details of who you are as a person. As they ask questions, they can get to know you better over time.</p>
<p>And on that note, you need a good photo of your smiling face.</p>
<h4 id="heading-how-to-make-a-social-media-headshot">How to Make a Social Media Headshot</h4>
<p>If you have the money, just find a local photographer and pay them to take some professional headshots.</p>
<p>You may even have a friend who's into photography, who can take them for free.</p>
<p>I took my headshot myself, using Photobooth, which comes pre-installed on MacOS. My friend spent about 10 minutes fixing some background and shading in Photoshop. He may have made my teeth slightly whiter. Here's what it looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/Michael_Headshot_B_W_Full_heic.png" alt="Image" width="600" height="400" loading="lazy">
<em>My headshot. I use this same photo everywhere.</em></p>
<p>Be sure to smile with your eyes, so you don't look robotic. Or better yet, think of something really funny, like I did here. Then the smile will be genuine.</p>
<p>Take a lot of shots from different angles, and just use whichever one looks best on you.</p>
<p>I recommend using a headshot that looks like how you look on any given day. Not a heavily photoshopped photo that tries to maximize your attractiveness. You want people at events to recognize you from your photo. And you don't want to intimidate people with your beauty. You want to put them at ease.</p>
<p>Speaking of putting people at ease: do <strong>not</strong> wear sunglasses, or try too hard to look cool. You want to look friendly and  approachable. A good acid test for this is: look at your photo. If you were lost, and saw this person on the street, would you be brave enough to ask them for directions?</p>
<p>Once you have chosen your headshot photo, use that same photo everywhere. Put it on all of your social media accounts. </p>
<p>Use it on your personal website. Even <a target="_blank" href="https://www.freecodecamp.org/news/gmail-profile-picture/">add the profile photo to your email account</a>.</p>
<p>I recommend using that same photo for years. Every time you change it, you run the risk that some people won't immediately recognize you. Even subtle changes in lighting, angle, or background can throw off people's familiarity.</p>
<p>Be sure to keep a high-definition version of the photo. That way people can use it to promote your talk at their conference, or your guest appearance on their podcast. (Don't worry – in time, you will get there.)</p>
<h3 id="heading-how-to-reach-out-to-people-from-your-past">How to Reach Out to People from your Past</h3>
<p>Now that you've got your bio and photos sorted out, you're ready to start talking with people.</p>
<p>15 years ago, I would say you should call people on the phone instead of messaging them. But culture has changed a lot with the introduction of smart phones. Most people will not respond well to a phone call.</p>
<p>Similarly, I don't recommend asking people out to coffee or lunch until much later in the conversation. People are busy, and may view the request as awkward.</p>
<p>You need to get to the point, and do so quickly.</p>
<p>So what is that point you need to get to?</p>
<p>Essentially:</p>
<ol>
<li>I know you</li>
<li>I like you</li>
<li>and I respect the work you're doing.</li>
</ol>
<p>That's it.</p>
<p>People like to be known. They like to be liked. They like for the work they do and the lives they live to be noticed.</p>
<p>Most of us get recognition on our birthdays. People from our past might send "happy birthday" text messages, social media posts, or even call us.</p>
<p>But what about the other 364 days of the year? People like to be recognized on those other days, too.</p>
<p>Well, here's a simple way you can recognize people.</p>
<p>Step 1: Research the person. Google them. Read through their most recent social media posts. Read through their LinkedIn. If they post family photos, actually take time to look at them.</p>
<p>Step 2: Think about something you could say that might make their day a bit brighter.</p>
<p>Step 3: Choose a social media platform they've been recently active on. Send them a direct message.</p>
<p>I'm going to share a template, but never use any templates verbatim, because if the recipient plugs your message into Google, they'll discover it's a template, and all your goodwill will be squandered.</p>
<p>If I were messaging someone I hadn't talked to in a few months or years out of the blue, I would say something like this:</p>
<p>"Hey [name], I hope your [new year / spring / week] is off to a fun start. Congrats on [new job / promotion / new baby / completed project]. It's inspiring to see you out there getting things done."</p>
<p>Something short and to the point like that. Greeting + congratulations + compliment. That is the basic formula.</p>
<p>Don't just say it. Mean it. </p>
<p>Really want this person to feel recognized. Really want to brighten their day. Really want to encourage them to keep progressing toward their goals.</p>
<p>Humans are very good at detecting insincerity. Don't try to over-sell it. Don't give them any reason to think "this person wants something from me."</p>
<p>That's why the most important thing about this is: be brief. Be respectful of people's time. Nobody wants a long letter that they'll feel obligated to respond to at length.</p>
<p>Because – say it with me again – <strong>people are busy.</strong></p>
<h3 id="heading-how-to-build-even-deeper-connections">How to Build Even Deeper Connections</h3>
<p>Because people are so busy, they're often tempted to see strangers more for what those strangers can do for them:</p>
<ul>
<li>This person drives the bus that gets me to work. </li>
<li>This person makes my beverage just the way I like it. </li>
<li>This person in HR answers my questions about time off.</li>
<li>This person put together a bangin' acid jazz playlist for me to listen to while I code. </li>
<li>This person sends me helpful emails each week with free coding resources.</li>
</ul>
<p>To some extent, you are what you do for people.</p>
<p>I know, I know. That might sound overly reductive. Cynical even. And that is 100% not true for the close friends and family in your life.</p>
<p>But for people who barely know you – who just encounter you while going about their day – this is likely how they see you.</p>
<p>You have to give people a reason to care about you. You have to inspire them to learn more about you.</p>
<p>Before you can become somebody's close friend – someone they truly care about, and think about when you're not around – you need to start off as someone who is helpful to them.</p>
<p>And that's what we're going to do here. We're going to build even deeper relationships by offering to help people.</p>
<p>This will be a long process. And you should start it well in advance of your job search. The last thing you want is for someone to think "Oh – you're just reaching out because you need something from me."</p>
<p>On the contrary – you're reaching out because you have something to offer them.</p>
<p>You are, after all, in possession of one of the most powerful skillsets a person can acquire. The ability to bend machines to your will. You are a programmer.</p>
<p><img src="https://atariage.com/2600/carts/c_BasicProgramming_Picture_front.jpg" alt="Image" width="400" height="483" loading="lazy">
<em>This is what being good at coding feels like.</em></p>
<p>Or, at least, you're on the road to becoming one.</p>
<p>So you already have a good pretext to reach out to people.</p>
<p>You may have heard the term "cold call". This is where you call someone knowing almost nothing about them, and trying to sell them something. This is not easy, and a vast majority of cold calls end with the other party hanging up.</p>
<p>But the more information you know about the other person, the warmer the call gets, and the more likely you are to succeed.</p>
<p>Now, you're not selling anything here. And as I mentioned earlier, you're not calling them either. You're sending them a direct message. </p>
<p>Maybe this is through Twitter, LinkedIn, Discord, Reddit – wherever. But you are reaching out to them with a single paragraph of text.</p>
<p>As I said, the strongest opening move – the approach that's most likely to get a response – is to casually offer help.</p>
<p>If I were doing this, here's a simple template I'd use. Remember not to use this template verbatim. Rewrite it in your own voice, how you would say it to a friend:</p>
<blockquote>
<p>"Hey [name], congrats on the [new job / promotion / new baby]. I've been learning some programming, and am building my portfolio. You immediately came to mind as someone who gets a lot of things done. Is there any sort of tool or app that would make your life easier? I may be able to code it up for you, for practice."</p>
</blockquote>
<p>This is a strong approach, because it is personalized and doesn't come across as automated. People get so many automated messages these days that they are quick to disregard anything that even resembles an automated message.</p>
<p>This is why I send all my messages manually, and don't rely on automation. It's better to slowly compose messages one-by-one than it is try and save time with a script or a mail-merge.</p>
<p>The fastest way to get blocked is to message someone with "Hi , how's it going?" where there's clearly a first name missing – evidence that the message is a template.</p>
<p>Sometimes I get a message using my last name instead of my first name. "Hey Larson." What, am I in military school now?</p>
<p>And a lot of people on LinkedIn have started putting an emoji at the beginning of their name. This makes it easy to detect automated messages, because nobody would include that emoji in their direct message.</p>
<p>When a message starts with: "Hi 🍜Sarah, are you looking for a new job?" Then you know it's a bulk message.</p>
<p>Also note that my above template does not say "we went to school together" or something like that. Unless you just met someone a few days ago, you shouldn't specify how you two know one another.</p>
<p>Why? Because the very act of reminding people how you know one another will prompt some people to step back and think: "Gee, I barely know this person."</p>
<h3 id="heading-how-to-keep-the-conversation-going">How to Keep the Conversation Going</h3>
<p>Again, your goal is to get a response from them, so you can start a back-and-forth conversation.</p>
<p>These messaging platforms have a casual feel to them. Keep it casual.</p>
<p>Don't send a single, multi-paragraph message. Keep your messages short and snappy. You don't want for it to feel like a chore to reply to you.</p>
<p>Once you've got them replying to you, start making notes on your Personal Network Board so you can remember these facts later.</p>
<p>Maybe they do have some app idea or tool idea. Great. Ask them questions about it. See if you can build it for them.</p>
<p>Start by sketching out a simple mockup of the user interface. Use graphing paper if you want to look extra sophisticated. Snap a photo of it and send it to them. "Something like this?"</p>
<p>This will establish that you're serious about helping them. And I'd be willing to bet for most people, this would be a new experience. </p>
<p>"You're helping me? You're creating this app for me?" It will be flattering, and they will be likely to remember it. Even if the app itself doesn't go anywhere.</p>
<p>From there, you can just go with the flow of conversation. Maybe it fizzles out. No worries. Let it. You can find a reason to pick the conversation back up a few weeks later.</p>
<p>The great thing about these social media direct messages is the entire message log is there. The next time you message them, they can just scroll up and see "oh – this is that person who offered to build that app for me." There are no more "who are you again?" head tilts that you might get during in-person conversations.</p>
<p>Again, keep everything casual and upbeat. If it feels like the conversation is going slow, that's no problem. Because you're going to have dozens of other conversations going. Other irons in the fire. You're going to be a busy bee building your network.</p>
<h3 id="heading-how-to-meet-new-people-and-expand-your-personal-network">How to Meet New People and Expand Your Personal Network</h3>
<p>We've talked about how to reach out to people you already know. Those connections are still there, even if they've atrophied a bit over the years.</p>
<p>But how do you make brand new connections?</p>
<p>This is no easy task. But I have some tips that will make this process a bit less daunting.</p>
<p>First of all, meeting people for the first time in person is so much more powerful than meeting them online.</p>
<p>When you meet someone in person, your memory has so much more information to latch onto:</p>
<ul>
<li>How the person looks, their posture, and how they move through the space</li>
<li>The sound of their voice and the way they speak</li>
<li>The lights, sounds, aromas, temperature, and the general feel of the venue</li>
<li>And so many other little details that get baked into your memory</li>
</ul>
<p>Spending 10 minutes talking with someone in person can build a deeper connection than dozens of messages back and forth, across weeks of correspondence.</p>
<p>This is why I strongly recommend: get out there and meet people at local events.</p>
<h3 id="heading-how-to-meet-people-at-local-events-around-town">How to Meet People at Local Events Around Town</h3>
<p>Which events? If you live in a densely-populated city, you may have a ton of options at your disposal. You may be able to go to tech events several nights each week, with minimal commuting.</p>
<p>If you live in a small town, you may have to stick with meeting people at local gatherings. Book fairs, ice cream socials, sporting events.</p>
<p>If you go to church, mosque, or temple, get to know people there, too.</p>
<p>And yes, I realize this may sound ridiculous. "That person standing in the bleachers next to me at the soccer game? They're somehow going to help me get a developer job?"</p>
<p>Maybe. Maybe not. But don't write people off. </p>
<p>That person may run a small business.</p>
<p>They may have gone to school with a friend who's a VP of Engineering at a Fortune 500 company.</p>
<p>And maybe – just maybe – they're a software engineer, too. After all, there are millions of us software engineers out there. And we don't all live in Silicon Valley. 😉</p>
<p>When you do meet a new person, you don't want to immediately pull out your phone and say "Can I add you to my LinkedIn professional network?"</p>
<p>Instead, you want to play it cool. Introduce yourself.</p>
<p><strong>Remember their name.</strong> Names are integral to building a relationship. If you are bad with names, practice remembering them. You can practice by just trying to remember the name of every character – no matter how minor they are – when you're watching TV shows or movies.</p>
<p>If you forget someone's name, don't guess. Just say "what's your name again" and be sure to remember it the second time.</p>
<p>Shake their hand or fist bump. Talk with them about whatever feels natural. If the conversation peters out, no worries. Let it.</p>
<p>You build relationships over time. It's not about total time spent with someone – it's about the number of times you meet that person over a longer span of time.</p>
<p>There's a good chance you will see the person again in the future. Maybe at that same exact location a few weeks later. And <strong>that</strong> is when you make your move:</p>
<p>"Hi [name] how's the [thing you talked about the previous time] going?"</p>
<p>Pick the conversation up where it left off. If they seem like someone who would be a helpful addition to your Personal Network Board, ask them "hey what are you doing next [day of week]? Do you want to come with me to [other upcoming local event]?"</p>
<p>Always have your upcoming week of events in mind, so you can invite people to join you.</p>
<p>This is a great way to get people to hang out with you in a safe, public space. And you're providing something of value – giving them awareness of an upcoming event.</p>
<p>If they seem interested, you can say "Awesome. What's the best way for me to message with you, and get you the event details?"</p>
<p>Boom – you now have their email or social media or phone number, and your relationship can unfold from there.</p>
<p>This may sound like a slow burn approach. Why be so cautious?</p>
<p>Again, people are busy. Smart people are defensive of their time, and of their personal information.</p>
<p>There are too many vampires out there who want to take advantage of people – trying to sell them something, scam them, get them into their multi-level marketing scheme, or in some other way proselytize them. </p>
<p>The best way to help other people get past this reflexive defensiveness is to already be on their radar from previous encounters as a reasonable person.</p>
<h3 id="heading-how-to-leverage-your-network">How to Leverage Your Network</h3>
<p>We'll talk more about how to leverage your network in Chapter 4. For now, look at your network purely as an investment of time and energy.</p>
<p>I like to think of my network as an orchard. I am planting relationships. Tending to them, and making sure they're healthy.</p>
<p>Who knows when those relationships will grow into trees and bear fruit. The goal is to keep planting trees, and at some point in the future, those trees will help sustain you.</p>
<p>Keep sending out positive energy. Keep offering to help people using your skills, and even your own network. (It is rarely a bad move to make a polite introduction between two people you know.)</p>
<p>Be a kind, thoughtful, helpful person. </p>
<p>Don't ever feel impatient with how slow a job search may be going.</p>
<p>Don't ever let yourself feel slighted or snubbed.</p>
<p>Don't ever let yourself feel jealous of someone else's success. </p>
<p>What goes around comes around. You will one day reap what you sow. And if you're sowing positive energy, you're setting yourself up for one bountiful harvest.</p>
<h2 id="heading-chapter-3-how-to-build-your-reputation">Chapter 3: How to Build Your Reputation</h2>
<blockquote>
<p>"The way to gain a good reputation is to endeavor to be what you desire to appear." – Socrates</p>
</blockquote>
<p>Now that you've started building your skills and your network, you're ready to start building your reputation.</p>
<p>You may be starting from scratch – a total newcomer to tech. Or you may already have some credibility you can bring with you from your other job.</p>
<p>In this chapter, I'll share practical tips for how you can build a sterling reputation among your peers. This will be the key to getting freelance clients, a first job, and advancing in your career.</p>
<p>But first, here's how I built my reputation.</p>
<h3 id="heading-story-time-how-did-a-teacher-in-his-30s-build-a-reputation-as-a-developer">Story Time: How Did a Teacher in His 30s Build a Reputation as a Developer?</h3>
<p><em>Last time on Story Time: Quincy started building his network of developers, entrepreneurs, and hiring managers in tech. He was frequenting hackerspaces and tech events around the city. But he had yet to climb into the arena and test his might...</em></p>
<p>I was already several months into my coding journey when I finally worked up the courage to go to my first hackathon.</p>
<p>One day I encountered a particularly nasty bug, and I wasn't sure how to fix it. So I did what a lot of people would do in that situation: I procrastinated by browsing the web. And that's when I saw it. Startup Weekend EDU.</p>
<p>Startup Weekend is a 54-hour competition that involves building an app, then pitching it to a panel of judges. These events reward your knowledge of coding, design, and entrepreneurship as well.</p>
<p>This particular event – held in the heart of Silicon Valley – had a panel of educators and education entrepreneurs as its judges. With my background in adult education, this seemed like an ideal first hackathon for me.</p>
<p>I told Steve about the event. And then I said the magic words: "I'll do the driving." Which was good, because Steve didn't have a driver's license.</p>
<p>With Steve onboard, we rounded out our team with a couple of devs from the Santa Barbara Hackerspace.</p>
<p>I spent weeks preparing for the event by researching the judges and the companies they worked for. I researched the sponsors. And of course, I practiced coding like a Shaolin monk.</p>
<p>Finally, after a month of preparation, it was the big weekend. We piled into my 2003 Toyota Corolla with the peeling clear coat, put on some high energy music, and started our 5-hour drive.</p>
<p>On the way up, we discussed what we should build. It would be education-focused, of course. Preferably catering to high school students, since those were the grade levels the judge's companies focused on. </p>
<p>But what should the app do? How was it going to make people's lives easier?</p>
<p>I thought back to my own time in high school. I didn't have much to go on, since I'd dropped out after just one year. (I did manage to study for and pass the GED – Good Enough Degree as we called it – while working at Taco Bell, before eventually going to college. But that's another story.)</p>
<p>But one pain point I did remember from high school, which still rang out after all these years: English papers.</p>
<p>Now I loved writing. But I didn't love writing in MLA format, with its rigid citation rules. I used to dread preparing a Work Cited page. My teacher would always dock me points for not formatting my citations correctly.</p>
<p>After listening to a lot of OK ideas from the other passengers in the car, I piped up. I said: "I have an idea. We should code an app that creates citations for you."</p>
<p>And someone laughed and said: "Out of sight."</p>
<p>And Steve said, "Hey that's a good name. We could call it Out of Cite with a 'C'."</p>
<p>We all laughed and felt clever. Then we started discussing the implementation details.</p>
<p>When we arrived at the venue, there were about 100 other devs there. It was an open-plan office space, with low-rise cubicles flanked by whiteboards.</p>
<p>I heard whispers about one of those developers. "Hey, it's that guy who won the event last year," I heard people say. They gestured in the direction of a cocky-looking dev surrounded by fans. "Maybe he'll let me be on his team."</p>
<p>The event started with pitches. Anyone could go up to the front of the room, grab the mic, and deliver a 60 second pitch for the app they wanted to build.</p>
<p>I was so nervous it felt like an alien was about to burst out of my chest. So naturally, I was first in line. Rip the band-aid off, right?</p>
<p>I was sweating and gesticulating wildly as I raced through my pitch. I said something like this: "Citations suck. I mean, they don't suck. They're necessary. And you need to add them to your papers. But preparing citations sucks. Let's build an app that will fill out your Work Cited page for you. Who's with me?"</p>
<p>The room was quiet. Then people realized I was finished talking, and they gave me an obligatory round of applause. The MC took the mic out of my hand and gave it to the next person, and I pranced back to my seat.</p>
<p>After pitches, it was time to form teams. Our Santa Barbara contingent looked at each other and said "I guess we're a team."</p>
<p>We figured out the wifi password and grabbed the choicest of workspaces: a corner office that had a door you could actually close.</p>
<p>I started scrawling UI mockups on whiteboard. I said, "We want something that's always a click away. Right in your browser's menu bar."</p>
<p>"Like a browser plugin," Steve said.</p>
<p>"Yeah. Let's build a browser plugin."</p>
<p>I showed them examples of the three formats that essays might require: MLA, APA, and Chicago.</p>
<p>"Could we generate all three of these at once, so they can just copy-paste them?" I asked.</p>
<p>"We can do better than that," Steve said. "We can have a button for each of them that puts the citation directly into their clipboard."</p>
<p>We worked fast, creating a simple MVP (Minimum Viable Product) by the end of Friday night. All it did was grab the current website's metadata and structure it as a citation. But it worked.</p>
<p>Since it was my first hackathon, I didn't want the stress of staying in a hostel. So I'd splurged to get a hotel room. We had two twin beds, so each night we'd rotate which of us had to sleep on the floor.</p>
<p>Saturday morning, our ambitions grew. I walked to the whiteboard and said to the team: "Citing websites is great and all. But a lot of the things students cite are in books or academic papers. We need to be able to generate citations for those, too."</p>
<p>We found an API that we could use to get citation information based on ISBN (a serial number used for books). And we hacked together a script that could search for academic papers based on their DOI (a serial number used for academic papers), then scrape data from the result page.</p>
<p>By Saturday night, the code for our browser plugin was really coming together. So I sat down and started preparing the presentation slides. I left a lot of the final coding to my teammates while I rehearsed my pitch over and over again for hours.</p>
<p>Even though it was my turn to sleep in a bed, I could barely get any shut-eye due to the jitters. Here I was, right in the heart of the tech ecosystem. Silicon Valley.</p>
<p>As a teacher, I would routinely give talks in front of my peers – sometimes dozens of them. But this was different.</p>
<p>In a few hours, I'd be presenting to a room full of ambitious developers. And judges. People with Ph.D.s, some of whom had founded their own tech companies. They were going to be evaluating our work. I was terrified I'd somehow blow it.</p>
<p>Unable to sleep, I opened my email. The Startup Weekend staff had sent out an email, which included a PDF of a book. It was an unofficial mash-up of the tech startup classics <a target="_blank" href="https://www.amazon.com/Four-Steps-Epiphany-Successful-Strategies/dp/1119690358?_encoding=UTF8&amp;qid=&amp;sr=&amp;linkCode=ll1&amp;tag=out0b4b-20&amp;linkId=662e9d222ccd9aa050d3ad29438e74e3&amp;language=en_US&amp;ref_=as_li_ss_tl">4 Steps to the Epiphany</a> and <a target="_blank" href="https://www.amazon.com/The-Lean-Startup-Eric-Ries-audiobook/dp/B005MM7HY8?_encoding=UTF8&amp;qid=&amp;sr=&amp;linkCode=ll1&amp;tag=out0b4b-20&amp;linkId=13b3c19bdbda93658336cf7c69e27100&amp;language=en_US&amp;ref_=as_li_ss_tl">The Lean Startup</a>.</p>
<p>Now, I had already read these books, because they were required reading for anyone who wanted to build software products in the early 2010s. But I had also read dozens of other startup books. And a lot of their insights sort of ran together into a slurry of advice.</p>
<p>It was 4 a.m., and I couldn't sleep. So I just started reading. One thing these books really hit on is building something that people will pay for. The ultimate form of customer validation.</p>
<p>That's when I realized: you know what would really push my presentation over the finish line? Proof of product-market fit. Proof that the app we were building solved a real problem people had. So much so that they'd open up their wallets.</p>
<p>This gave me an idea. I should take our app on the road and sell it to people.</p>
<p>But it was Sunday morning. Where was I going to find potential customers? Well, our hotel just happened to be located near the main campus of Stanford University.</p>
<p>I drove my team to the event venue, waved goodbye and said: "I'll come back when I have cold, hard cash from customers." </p>
<p>My teammates chuckled. I'm not sure if they thought I was serious. They said, "Just don't be late for the pitch."</p>
<p>But I was serious. I had a prototype of the app running on my laptop. I punched Stanford into my GPS and embarked on my mission.</p>
<p>Now, I studied at a really inexpensive state university in Oklahoma. So I felt really out of my depth when I rolled up to one of the premier universities in the world.</p>
<p>Stanford costs $50,000 per year to attend. And I pulled into their parking lot driving a car worth 1/10th of that.</p>
<p>The campus was a ghost town this time of the week. But a palatial ghost town, nonetheless. Bronze statues. Iconic arches everywhere.</p>
<p>I asked myself: where are the most high-achieving, hard-core students this time of day? The ones who don't have time to waste on manually creating their Work Cited pages?</p>
<p>I walked into the main library, right past the security desk and a sign that said "no soliciting."</p>
<p>I strode around the stacks, finding a small handful of people studying. This one kid was studiously taking notes as he read through a thick textbook. Bingo.</p>
<p>I slid into the seat next to him. "Psst. Hey. Do you like citations?"</p>
<p>"What?"</p>
<p>"Citations. You know, like, work cited pages."</p>
<p>"Um..."</p>
<p>"You know, the last page of your paper, where you have to list all the..."</p>
<p>"I know what a work cited page is."</p>
<p>"OK. Well check this out." I pulled my jacket to the side like a drug dealer, and whipped out my $200 netbook. He humored me for a moment while I delivered my awkward sales pitch.</p>
<p>I said: "Here. I've got this browser plugin. I go to any website, click the button, and voilà. It will create a citation for me."</p>
<p>The kid raised his eyebrows. "Can it do MLA?"</p>
<p>I bit back my excitement and said, "MLA, APA, and even Chicago. Watch." I clicked the button and three citations appeared – each with its own copy-to-clipboard button.</p>
<p>The kid nodded, seeming somewhat impressed. So I attempted to close the sale.</p>
<p>"What if I told you that I was about to launch this app with a yearly subscription. But if you sign up now, I'll get unlimited access not for a year, but for a lifetime."</p>
<p>The kid thought for a moment.</p>
<p>I had heard that silence was the salesperson's best friend. So I sat there for an uncomfortably long time in total silence, staring him down.</p>
<p>Finally he said: "Cool I'm in."</p>
<p>"Awesome. That'll be twenty bucks."</p>
<p>The kid recoiled. "What? That's expensive."</p>
<p>This was of course the era of venture capital-subsidized startups, where Uber and Lyft were losing money on every ride in a race for market share. So the kid's reaction was not totally surprising.</p>
<p>But I thought fast. "Well, how much cash do you have on you?"</p>
<p>He fumbled with his wallet, then said, "five bucks."</p>
<p>I looked at the crumpled bill and shrugged. "Sold."</p>
<p>He smiled, and I sent him an email with instructions for how to install it. Then I said, "One more thing. Let's take a picture together." </p>
<p>I put my phone on selfie mode. He started to smile, and I said, "Here. Hold up the five dollar bill."</p>
<p>I spent another hour pitching people in the library, and managed to get another paying customer as well. Then I raced back to the event venue to finalize our prototype with the team.</p>
<p>That afternoon, I gave what I still think is the best presentation of my life. We live-demoed the working app – which worked perfectly.</p>
<p>We ended the presentation with the photos I'd taken, posing with Stanford students who were now our paying customers. When I held up the cash we earned, the audience burst into applause.</p>
<p>Overall, it was one of the most exhilarating experiences of my life. We came in second place, and won some API credit from one of the companies who sponsored the event.</p>
<p>At the after party, I chipmunked some pizza, so I'd have more time to network with everyone I could. I connected on LinkedIn. I followed on Twitter. I snapped selfies together with people and used the heck out of the event's hashtag.</p>
<p>This was a watershed moment in my coding journey. I had proven to the people in that room that I could help design, code, and even sell an app. And more importantly, I'd proven it to myself.</p>
<h3 id="heading-riding-the-hackathon-circuit">Riding the Hackathon Circuit</h3>
<p>From that moment on, I was hooked on hackathons. That year, I participated in dozens of them. I became a road warrior, railing up and down the coast, attending every competition I could.</p>
<p>It would be much harder from here on out. I didn't have a team anymore. I was on my own. </p>
<p>I'd arrive, meet as many people as I could, then go up and pitch an idea I thought might win over the judges.</p>
<p>Sometimes people joined my team. Sometimes I joined other people's teams.</p>
<p>I didn't merely want to design apps – I wanted to code them, too. And my reach often exceeded my grasp.</p>
<p>There were many hackathons where I would still be trying to fix bugs down to the final minutes before going on stage. Sometimes my apps would crash during live demos.</p>
<p>One hackathon in Las Vegas, I managed to screw up the codebase so badly that we just had to use a slideshow. I sat in the audience with my head in my hands, watching helplessly as my team member demonstrated how our app would hypothetically work – if I could have gotten it to work. We didn't fare well with the judges.</p>
<p>But I kept grinding. Kept arriving in new towns, checking into the hostel, and hitting the venue, and eating as much free pizza as I could.</p>
<p>My teams had come in second or third so many times I could barely keep count. But we'd never managed to outright win a hackathon.</p>
<h3 id="heading-breaking-through">Breaking Through</h3>
<p>That was until an event in San Diego. I'll never forget the feeling of building something that won over the audience and judges to the extent that our victory felt like a foregone conclusion. </p>
<p>After they announced us as the winner, I remember sneaking out the back door to a parking lot and calling my grandparents. I told them that I'd finally done it. I'd helped build an app and craft a pitch that had won a hackathon.</p>
<p>I don't know how much my grandparents understood about software development, or about hackathons. But they said they were proud of me.</p>
<p>With them gone now, I often think back to this conversation. I cherish their encouragement. Their faith in a 30-something teacher grandson could try like crazy and become a developer.</p>
<p>I kept going to hackathons after that. I kept forming new teams and learning new tools along the way. You never forget the first time you get an API to work. Or when you finally grok how some Git command works. And you never forget the people hustling alongside you, trying to get the app to hold together through the demo.</p>
<p>The TechCrunch Disrupt hackathon. The DeveloperWeek hackathon. The ProgrammableWeb hackathon. The $1 Million Prize Salesforce Hackathon. So many big hackathons and so much learning. This was the crucible where my developer chops were forged.</p>
<p>Not only did I manage to build my skills and my network along the way – I now had a reputation as someone who could actually win a hackathon.</p>
<p>I could ship.</p>
<p>This made me a known quantity.</p>
<p>And that reputation was crucial to getting my first freelance clients, my first developer job, and most importantly – trusting my own instincts as a dev.</p>
<h3 id="heading-why-your-reputation-is-so-important">Why Your Reputation is So Important</h3>
<p>The role of reputation in society goes way, way back to human prehistory. In most tribes and settlements, there was some system to keep track of who owed what to whom.</p>
<p>Before there was cash, there was credit.</p>
<p>This may have been a written ledger. Or it may have been an elder who simply kept all these records in their head.</p>
<p>Beyond raw accounting, there was also a less tangible, but equally important vibe that people carried with them.</p>
<p>"John sure knows how to shoe a horse." </p>
<p>Or "Jane is the best story teller in the land." </p>
<p>Or "Jay's courage in battle saved us against the invaders three winters ago."</p>
<p>You'll note that these examples all involve someone being good at something. Not merely being a good, likable person.</p>
<p>It certainly helps to be a chill, down-to-earth human being. But this isn't The Big Lebowski, and we aren't going to survive on our charm alone.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/image__2000-1338_.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Big Lebowski (left). He had no job, he had no skills, he had no energy. But he had chill, out the wazoo.</em></p>
<p>It's easy for a developer to say: "Oh yeah. I know JavaScript like the back of my hand. I can build you any kind of JavaScript application you need, running on any device you can think of."</p>
<p>Or to say: "I ship code under budget and ahead of time – all the time."</p>
<p>But how do you know they're not exaggerating their claims?</p>
<p>After all, a devious man once said:</p>
<blockquote>
<p>"If you can only be good at one thing, be good at lying.   </p>
<p>Then you're good at everything."</p>
</blockquote>
<p>(The true provenance of this quote is unknown. But I like to imagine it was said by a 1920s con man wearing a top hat and a monocle.)</p>
<p>Anyone can lie. And some people do.</p>
<p>Earlier in my career, I had the unpleasant task of firing a teacher who had lied about earning a master's degree. The years went by and nobody caught it. </p>
<p>Every year, he would lie on his annual paperwork, so that he could get a higher pay raise than the other teachers. And every year, he would get away with it.</p>
<p>But one day a small discrepancy tipped me off. I reviewed his file, called up some university record departments, and discovered that he had never bothered finishing his degree. </p>
<p>When I caught him it was a real Scooby Doo moment. "And I would have gotten away with it, if not for you darn kids."</p>
<p>It sucked to know that this person was teaching at the school for years and getting paid more than many of the other teachers – just because he was willing to lie.</p>
<p>The spoils of lying are always there, glistening. Some people are willing to give in to that temptation.</p>
<p>Employers know this. They know you can't trust just any person who claims to know full-stack JavaScript development. You have to be cautious about who gets a company badge, a company email address, and the keys to your production databases.</p>
<p>This is why employers use behavioral interview questions – to try and catch people who are more capable of dishonesty.</p>
<p>Call me naive, but I believe that most people are inherently good. That most people are willing to play by the rules as long as those rules are reasonably fair.</p>
<p>But if even one person out of ten would be a disaster hire, it means that all of us are subjected to higher scrutiny. </p>
<p>The worst-case scenario is not merely someone who lies to make more money. It's someone who sells company secrets, destroys relationships with customers, or breaks laws in the name of inflating their numbers. </p>
<p>History is rife with employees who unleashed catastrophic damage upon their employers, all for their own personal gain.</p>
<p>Thus, the developer hiring process at most big companies is paranoid as heck. Maybe it should be. But unfortunately, this makes it harder for <em>everyone</em> to get a developer job – even the most honest of candidates.</p>
<p>As developers, we need proof that our skills are as strong as we say they are. We need proof that our work ethic is as steadfast as our employers need it to be.</p>
<p>That's where reputation comes in. It reduces ambiguity. It reduces counter-party risk. It makes it safer for employers to make a job offer, and to sign an employment contract with you.</p>
<p>This means that – if you have a strong enough reputation – you may be able to get into the company through a side door – rather than the front door that other applicants line up for.</p>
<p>Some companies even have in-house recruiters who can fast track your interview process. A strong reputation can also help you command more bargaining power during salary negotiations.</p>
<p>So let's talk about how you can build a strong reputation, and become sought-after by managers.</p>
<h3 id="heading-how-to-build-your-reputation-as-a-developer">How to Build Your Reputation as a Developer</h3>
<p>There are at least six time-tested ways you can build your reputation as a developer. These are:</p>
<ol>
<li>Hackathons</li>
<li>Contributing to open source</li>
<li>Creating Developer-focused content</li>
<li>Rising in the ranks working at companies who have a "household name"</li>
<li>Building a portfolio of freelance clients</li>
<li>Starting your own open source project, company, or charity</li>
</ol>
<h4 id="heading-how-to-find-hackathons-and-other-developer-competitions">How to Find Hackathons and Other Developer Competitions</h4>
<p>Hackathons represent the most immediate way to build your reputation, your network, and your coding skills at the same time.</p>
<p>Most hackathons are free, and open to the public. You just need to have the time and the budget to travel.</p>
<p>If you live in a city with lots of hackathons – like San Francisco, New York, Bengaluru, or Beijing – you may be able to commute to the event, then go home and sleep in your own bed.</p>
<p>Even though I lived in Santa Barbara, which only had hackathons once every few months, I did have an old classmate in San Francisco who let me crash on his couch. This gave me access to many more events.</p>
<p>Hackathons used to be hard core events. People would knock back energy drinks and sleep on floors, all to finish their project by pitch time.</p>
<p>But hackathon organizers are gradually becoming more mindful about the health and sustainability of these events. After all, a lot of participants have kids, or demanding full-time jobs, and can't just all-out code for an entire weekend.</p>
<p>The best way to find upcoming events is to just google "hackathon [your city name]" and browse the various event calendars that come up in the search results. Many of these will be run by universities, local employers, or even education-focused charities.</p>
<p>If you're playing to win, I recommend doing your research ahead of time. </p>
<p>Who are the event sponsors? Usually it will be Business-to-Developer type companies, with APIs, database tools, or various Software-as-a-Service offerings.</p>
<p>These sponsors will probably have a booth at the event where you can talk with their developer advocates. These are people who get paid to teach people how to use the company's tools. Sometimes you'll even meet key employees or founders at these booths, which can be a great networking opportunity, too.</p>
<p>Often the hackathon will offer sponsor-specific prizes. "Best Use of [sponsor's] API." It may be easier to focus your time on incorporating specific sponsor tools into your project, rather than trying to win the grand prize. You can still put these down as wins on your LinkedIn or your résumé. A win is a win.</p>
<p>Sometimes the hackathon is just so high profile – or the prize is so substantial – that is just makes sense to try and win the competition outright.</p>
<p>During my time going to hackathons, I was able to win several months' rent worth of cash prizes, several years' worth of free co-working space, and even a private tour of the United Nations building in New York City.</p>
<p>On the hackathon circuit, I met people whose main source of income was cash prizes from winning hackathons. One dev I knew managed to win nine sponsor prizes at the same hackathon. He managed to integrate all of those sponsor tools into his project – and also win second place overall.</p>
<p>Don't be surprised if some of the people you run into frequently at hackathons go on to found venture-backed companies, or launch prominent open source projects.</p>
<p>The level of ambition you'll see among hackathon regulars is way, way higher than that of the average developer. These are, after all, people who finish a work week, then go straight into a work weekend. These people are not afraid to leap out of the frying pan and into the fire.</p>
<h3 id="heading-how-to-contribute-to-open-source">How to Contribute to Open Source</h3>
<p>Contributing to open source is one of the most immediate ways you can build your reputation. Most employers are going to look at your GitHub profile, which will prominently display your Git commit history.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/raisedadead__Mrugesh_Mohapatra__--.png" alt="Image" width="600" height="400" loading="lazy">
<em>The GitHub profile of Mrugesh Mohapatra, who does a ton of platform development and DevOps for freeCodeCamp.org. Note how green his activity bar is. 2,208 contributions in the past year alone.</em></p>
<p>Many open source project maintainers, such as Linux Foundation, Mozilla (Firefox), and of course freeCodeCamp ourselves, have high standards for code quality.</p>
<p>You can read through open GitHub issues to find known bugs or feature requests. Then you can make the code changes and open a pull request. If the maintainers merge your pull request, this will be a major feather in your cap.</p>
<p>One of the best ways to get a job at a tech company is to become a prolific open source contributor to their repositories.</p>
<p>Open source contribution is a great way to build your reputation because everything you do is right out in public. And you get the <strong>social proof</strong> of having other developers review and accept your work.</p>
<p>If you're interested in building your reputation through open source, here's how to get started.</p>
<p>Read Hillary Nyakundi's comprehensive guide to <a target="_blank" href="https://www.freecodecamp.org/news/how-to-contribute-to-open-source-projects-beginners-guide/">getting started with open source</a>.</p>
<h3 id="heading-how-to-create-developer-focused-content">How to Create Developer-Focused Content</h3>
<p>Developers are people. And like other people, they want something to do with their time when they're not working, sleeping, or hanging with friends and family.</p>
<p>For many people – including myself – that means spending time in other people's thoughts. Books. Video essays. Interactive experiences like <a target="_blank" href="https://www.freecodecamp.org/news/learn-to-code-rpg-1-5-update/">visual novels</a>.</p>
<p>You can broadly refer to these as "content." I'm not a huge fan of the word, because it makes these works feel disposable. But that's what people call it.</p>
<p>Software development is an incredibly broad field, with so many different topics you could approach. There are developer lifestyle vlogs, coding interview prep tutorials, coding live streams on Twitch, and <a target="_blank" href="https://www.freecodecamp.org/news/tag/podcast/">developer interview podcasts like the freeCodeCamp Podcast</a>.</p>
<p>There are probably entire categories of developer content that we haven't even thought of yet, which will break over the next decade.</p>
<p>If you're interested in film, journalism, or creative writing, developer content may be a good way to build your reputation.</p>
<p>You can pick a specific topic and gradually come to be seen as the expert.</p>
<p>There are developers who specialize in tutorials for specific technology stacks, for example.</p>
<p>My friend Andrew Brown is a former CTO from Toronto who has passed all the major DevOps exams. He creates <a target="_blank" href="https://www.freecodecamp.org/news/azure-developer-certification-az-204-pass-the-exam-with-this-free-13-5-hour-course/">free courses to prepare you for all the AWS, Azure, and Google Cloud certifications</a>, and also runs an exam prep service.</p>
<p>There are more than 30 million software developers around the world. That's a lot of people who will potentially consume your content, and who will come to know who you are.</p>
<h3 id="heading-how-to-rise-in-the-ranks-by-working-at-big-companies">How to Rise in the Ranks by Working at Big Companies</h3>
<p>You may have seen a developer introduced as an "Ex-Googler" or an "Ex-Netflix engineer."</p>
<p>Some tech companies have such rigorous hiring processes – and such high standards – that even getting a job at the company is a big accomplishment.</p>
<p>There are some practical reasons why employers look at where candidates have previously worked. It reduces the risk of a bad hire.</p>
<p>You can build up your reputation by working your way up the prestige hierarchy. You can ladder from a local employer to a Fortune 500 company, and ultimately to one of the big tech giants.</p>
<p>Of course, working at a giant corporation is not for everyone. I'll talk about this more in Chapter 4. But know that it is one option you have for building up your reputation.</p>
<h3 id="heading-how-to-build-your-reputation-by-building-a-portfolio-of-freelance-clients">How to Build your Reputation by Building a Portfolio of Freelance Clients</h3>
<p>You can build your reputation by working with companies as a freelancer.</p>
<p>Freelance developers usually work on smaller one-person projects. So this may be a better strategy for building your reputation locally.</p>
<p>For example, if you did good work for a locally-based bank, that may be enough to convince a local law firm to contract you as well.</p>
<p>There is something to be said for being a "hometown hero." I know many developers who can effectively compete with online competition just by being physically present in meetings, and knowing people locally.</p>
<h3 id="heading-how-to-build-a-developer-portfolio-of-your-work">How to Build a Developer Portfolio of Your Work</h3>
<p>Once you've built some projects, you'll want to show them off. And the best way to do this is with short videos.</p>
<p>People are busy. They don't have time to pull down your code and run it on their own computer. </p>
<p>And if you send people to a website, they may not fully grasp what they're looking at, and why it's so special.</p>
<p>That's why I recommend you use a screen capture tool to record 2 minute video demos.</p>
<p>Two minutes should be long enough to show how the project works. And once you've done that, you can explain some of the implementation details, and design decisions you made.</p>
<p>But always, always start with the demo. People want to see something work. They want to see something visual.</p>
<p>Once you've lured people in with your compelling demo of your app running, you can explain all the details you want. Your audience will now have more context, and be more interested.</p>
<p>Two minutes is also a magic length, because you can upload that video to a tweet, and it will auto-play on Twitter as people scroll past it. Auto-play videos are much, much more likely to be watched on Twitter. They remove the friction of having to click a play button, or navigate to another website.</p>
<div class="embed-wrapper">
        <blockquote class="twitter-tweet">
          <a href="https://twitter.com/ossia/status/1603405016525688834"></a>
        </blockquote>
        <script defer="" src="https://platform.twitter.com/widgets.js" charset="utf-8"></script></div>
<p>You can put these project demo videos on websites like YouTube, Twitter, your GitHub profile, and of course your own portfolio website.</p>
<p>For capturing this video, I recommend using QuickTime, which comes built-in with MacOS. And if you're on Windows, you can use Game Recorder, which comes free in Windows 10.</p>
<p>And if you want a more powerful tool, OBS is free and open source. It's harder to learn, but infinitely customizable.</p>
<p>As far as recording tips: keep your font size as large as possible, and use an external mic. Any mic you can find – even from cheap headphones – will be better than speaking into your laptop's built in mic.</p>
<p>Invest as much time as you need to in recording and re-recording takes until you nail it.</p>
<p>Being able to demo your projects and present your code is a valuable skill you'll use throughout your career. Time spent practicing pitching is never wasted.</p>
<h3 id="heading-how-to-start-your-own-open-source-project-company-or-charity">How to Start Your Own Open Source Project, Company, or Charity</h3>
<p>Being a founder is the fastest – but also riskiest – way to build a reputation as a developer. </p>
<p>It's riskiest because you're wagering your time, your money, and possibly even your personal relationships – all for an unknown outcome.</p>
<p>If you contribute to open source for long enough, you <em>will</em> build a reputation as a developer.</p>
<p>If you grind the hackathon circuit for long enough, you <em>will</em> build a reputation as a developer<em>.</em></p>
<p>But you could attempt to start entrepreneurial projects for decades without getting traction. And squander your time, money, and connections along the way.</p>
<p>Entrepreneurship is beyond the scope of this book. But if you're interested in it, I will give you this quick advice:</p>
<p><strong>Most entrepreneurs fail</strong>. Some fail due to circumstances outside their control. But a lot fail due to not understanding the nature of the risks they're taking on.</p>
<p>Don't rush into founding a project, company, or charity. Try to work for other organizations who are already doing work in your field of interest.</p>
<p>By working for someone else, you get paid to learn. You get exposure to the work, and the risks surrounding it. And you can build savings for an eventual entrepreneurial venture.</p>
<h2 id="heading-how-not-to-destroy-your-reputation">How Not to Destroy Your Reputation</h2>
<blockquote>
<p>"It takes a lifetime to build a good reputation, but you can lose it in a minute." – Will Rogers, Actor, Cowboy, and one of my heroes growing up in Oklahoma City</p>
</blockquote>
<p>Building your reputation is a marathon, not a sprint. </p>
<p>It may take years to build up a reputation strong enough to open the right doors.</p>
<p>But just like in a competitive marathon, a stumble can cost you valuable time. A stumble that results in injury may put you out of the race completely.</p>
<h3 id="heading-dont-say-dumb-things-on-the-internet">Don't Say Dumb Things on the Internet</h3>
<p>People used to say dumb things all the time. The words might hang in the air for a few minutes while everyone winced. But the words did eventually dissipate.</p>
<p>Now when people say dumb things, they often do so online. And in indelible ink.</p>
<p>Always assume that the moment you type something into a website and press enter, it's going to be saved to a database. That database is going to be backed up across several data centers around the world.</p>
<p>You can prove the existence of data, but there is no way to prove the absence of data.</p>
<p>You should assume, for all intents and purposes, that the cat is out of the bag. There's no getting the cat back in the bag. Whatever you just said: that's on your permanent record.</p>
<p>You can delete the remark. You can delete your account. You can even try to scrub it from Google search results. But someone has probably already backed it up on the Wayback Machine. And when one of those databases inevitably gets hacked years from now, those data will probably still be in there somewhere, ready for someone to resurface them.</p>
<p>It is a scary time to be a loud mouth. So don't be. Think before you speak.</p>
<p>My advice, which may sound cowardly: get out of the habit of arguing with people online.</p>
<p>Some people abide by the playground rule of "if you don't have something nice to say, don't say anything at all."</p>
<p>I prefer the "praise in public, criticize in private." </p>
<p>I will publicly recognize good work someone is doing in the developer community. If I see a project that impresses me, I will say so.</p>
<p>But I generally refrain from tearing people down. Even people who deserve it.</p>
<p>In a fight, everyone looks dirty.</p>
<p>You don't want to look wrathful, tearing apart someone's argument, or dog piling in on someone who just said something dumb.</p>
<p>Sure – caustic wit can win you internet points in the short term. But it can also make people love you a little bit less and fear you a little bit more.</p>
<p>I also try to refrain from complaining. Yes, I could probably get better customer service if I threatened to tweet about a cancelled flight.</p>
<p>But people are busy. Most of them don't want to use their scarce time, scrolling through social media, only to see me groaning about what is in the grand scheme of things a mild inconvenience.</p>
<p>So that is my advice on using social media. Try to keep it positive.</p>
<p>If it's a matter that you believe strongly about, I won't stop you from speaking your mind. Just think before you type, and think before you hit send.</p>
<h3 id="heading-dont-over-promise-and-under-deliver">Don't Over-promise and Under-deliver</h3>
<p>One of the most common ways I see developers torpedo their own reputations is to over-promise and under-deliver. This is not necessarily a fatal error. But it is bad.</p>
<p>Remember when I talked about the Las Vegas hackathon where I utterly failed to finish the project in time for the pitch, and we had to use slides instead of a working app? </p>
<p>Yeah, that was one of the lowest points in my learn to code journey. My teammates were polite, but I'm sure they were disappointed in me. After all, I had been overconfident. I had over-promised what I'd be able to achieve in that time frame, and I had under-delivered.</p>
<p>It is much better to be modest in your estimations of your abilities.</p>
<p>Remember the parable of Icarus, who on wax wings flew too close to the sun. If only he'd taken a more measured approach. Ascended a bit slower. Then his wings wouldn't have melted, and he wouldn't have plunged into the sea, leaving a guilt-stricken father.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/1690px-Pieter_Bruegel_de_Oude_-_De_val_van_Icarus.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Landscape with the Fall of Icarus by Pieter Bruegel the Elder, circa 1560. Icarus coulda been a contender. He coulda been somebody. But instead, he's just legs disappearing into the sea. And the farmers and the shepherds can't be bothered to look up from their work to take in his insignificance.</em></p>
<h3 id="heading-get-addictions-under-control-before-they-damage-your-reputation">Get Addictions Under Control Before They Damage Your Reputation</h3>
<p>If you have an untreated drug, alcohol, or gambling addiction, seek help first. The developer job search can be a long, grueling one. You want to go into it with your full attention.</p>
<p>Even something as seemingly harmless as video game addiction can distract you, and soak up too much of your time. It's worth getting it under control first.</p>
<p>I am not a doctor. And I'm not going to give you a "drugs are bad" speech. But I will say: you may hear of Silicon Valley fads, where developers abuse drugs thinking they can somehow improve their coding or problem solving abilities.</p>
<p>For a while there was a "micro-dosing LSD" trend. There was a pharmaceutical amphetamines trend.</p>
<p>My gut reaction to that is: any edge these may give you is probably unsustainable, and a net negative over a longer time period.</p>
<p>Don't feel peer pressure to take psychoactive drugs. Don't feel peer pressure to drink at happy hours. (I haven't drank so much as a beer since my daughter was born 8 years ago, and I don't feel like I've missed out on anything at all.)</p>
<p>If you are in recovery from addiction, be mindful that learning to code and getting a developer job will be a stressful process. Pace yourself, so you don't risk a relapse.</p>
<p>You do not want to reach the end of the career transition process – and achieve so much – only to have old habits resurface and undo your hard work.</p>
<h3 id="heading-try-and-separate-your-professional-life-from-your-personal-life">Try and Separate Your Professional Life From Your Personal Life</h3>
<p>You may have heard the expression, "Don't mix business with pleasure."</p>
<p>As a developer, you are going to become a powerful person. You are going to command a certain degree of respect from other people in your city.</p>
<p>Maybe not as much as a doctor or an astronaut. But still. People are going to look up to you.</p>
<p>You're going to talk with people who would love to be in your shoes.</p>
<p>Do not flaunt your wealth.</p>
<p>Do not act as though you're smarter than everybody else.</p>
<p>Do not abuse the power dynamic to get what you want in relationships.</p>
<p>This will make you unlikable to the people around you. And if it's somehow captured and posted online, it may go on to haunt you for the rest of your career.</p>
<p>Never lose sight of how much you have. And how much you have to lose.</p>
<h3 id="heading-use-the-narrator-trick">Use the Narrator Trick</h3>
<p>I'll close this chapter with a little trick I use to pump myself up.</p>
<p>First, remember that you are the hero in your own coding journey. In the theater of your mind, you are the person everyone's watching – the one they are rooting for.</p>
<p>The Narrator Trick is to narrate your actions in your head as you do them.</p>
<blockquote>
<p>Quincy strides across the hackerspace, his laptop tucked under his arm. He sets his mug under the hot water dispenser and drops in a fresh tea bag. He pulls back the lever. And as the steaming water fills his mug, he says aloud in his best British accent: "Tea. Earl Grey. Hot."  </p>
<p>His energizing beverage in hand, he slides into a booth, squares his laptop on the surface, and catches the glance of a fellow developer. They lock eyes for a second. Quincy bows his head ever-so-slightly, acknowledging the dev's presence. The dev bows back, almost telepathically sharing this sentiment: "I see you friend. I see you showing up. I see you getting things done."</p>
</blockquote>
<p>This may sound ridiculous. Why yes, it is ridiculous. But I do it all the time. And it works.</p>
<p>Narrating even the most mundane moments of your life in your head can help energize you. Crystalize the moment laid out before you, and give you clarity of purpose.</p>
<p>And this works even better when you think of your life in terms of eras ("the Taco Bell years"). Or inflection points ("passing the GED exam").</p>
<p>What does this have to do with building your reputation? Your reputation is essentially the summary of who you are. What you mean to people around you.</p>
<p>By taking yourself more seriously, by thinking about your life as a movie, you're gradually working through who you are. And who you want to one day become.</p>
<p>By narrating your actions, you shine a brighter light on them in your own mind. Why did I just do that? What was I thinking? Was there a better move there?</p>
<p>So many people sabotage their reputations without even realizing it, just because they've settled into bad habits.</p>
<p>For years I thought I had to be "funny" all the time. I would find any opportunity to inject some self-deprecating humor. A lot of people realized what I was doing and found it amusing. But a lot of them didn't understand, and just got the impression I was a jerk. </p>
<p>Why did I do that? I think it went back to grade school, when I was always trying to be the class clown and make people laugh. </p>
<p>But decades later, this reflex to fill silence with laughter was not serving me well.</p>
<blockquote>
<p>"When you repeat a mistake, it's not a mistake anymore. It's a decision." – Paulo Coelho</p>
</blockquote>
<p>I might have gone on much longer without noticing this bad habit. But with the Narrator Trick, the awkwardness of my behavior was laid bare.</p>
<p>I'm sure I've got lots of other ways of thinking and ways of doing things that are suboptimal. And with the help of the Narrator Trick, I'm hoping to identify them in the future and refine them, before they give people the wrong impression.</p>
<h3 id="heading-your-reputation-will-become-your-legacy">Your Reputation Will Become Your Legacy.</h3>
<p>Think about who you want to be at the end of your story. How you want people to think of your time on Earth. Then work backward from there. </p>
<p>The person you want to be at the end of the movie. That hero you want people to admire. Why not start carrying yourself like that now?</p>
<p>Can you imagine what it would be like to be a successful developer? To have built software systems that people rely upon?</p>
<p>That future you – how would they think? How would they approach situations and solve problems? How would they talk about their accomplishments? Their setbacks?</p>
<p>Merely thinking about your future self can help you clarify your thinking. Your priorities.</p>
<p>I often think of "Old Man Quincy", with his bad back. He has to excuse himself to run to the toilet every 30 minutes. </p>
<p>But Old Man Quincy still tries his best to work with what he has. He moves in spite of sore joints. He ponders in spite of a foggy mind. </p>
<p>Old Man Quincy still wants to get things done. He's proud of what he's accomplished, but he doesn't spend much time looking back. He looks forward at what he's going to do that day, and what goals he's going to accomplish.</p>
<p>I often think about Old Man Quincy, and work backward to where I am today. </p>
<p>What decisions can I make today that will set me up for being someone worthy of admiration tomorrow? Do I have to wait decades to earn that reputation? Or can I borrow some of that respect from the future?</p>
<p>By thinking like my future self might think, can I make moves that earn me a positive reputation in the present?</p>
<p>I believe that you can leverage your future reputation – your legacy – right now. Just think in terms of your future self and what you'll accomplish. And use that as a waypoint to guide you forward.</p>
<p>I hope that these tools – the Narrator Trick and the visualizing your future self trick – help you not only think about the nature of reputation. I hope they also help you take concrete steps toward improving your reputation.</p>
<p>Because building a reputation – making a name for yourself – is the surest path to sustainable success as a developer.</p>
<p>Success can mean many things to many people. But most people – from most cultures – would agree: one big aspect of success is putting food on the table for yourself and your family.</p>
<p>And that's what we're going to talk about next.</p>
<h2 id="heading-chapter-4-how-to-get-paid-to-code-freelance-clients-and-the-job-search">Chapter 4: How to Get Paid to Code – Freelance Clients and the Job Search</h2>
<p>If you've been building your skills, your network, and your reputation, then getting a developer job is not all that complicated.</p>
<p>Note that I said it's not complicated – it's still a lot of work. And it can be a grind.</p>
<p>First, let me tell you how I got my first job.</p>
<h3 id="heading-story-time-how-did-a-teacher-in-his-30s-get-his-first-developer-job">Story Time: How Did a Teacher in His 30s Get His First Developer Job?</h3>
<p><em>Last time on Story Time: Quincy hit the hackathon circuit hard, even winning a few of the events. He was building his reputation as a developer who was "dangerous" with JavaScript. Not super skilled. Just dangerous...</em></p>
<p>I had just finished a long day of learning at the Santa Barbara downtown library, sipping tea and building projects.</p>
<p>The best thing about living in California is the weather. We'd joke that when you rented an exorbitantly-priced one-bedroom apartment in the suburbs, you were not paying for the inside – you were paying for the outside.</p>
<p>My goal was to spend as little time in that cramped 100-year old rat trap as necessary, and to spend the rest out walking around town.</p>
<p>It was a beautiful Wednesday evening. I still had two more days to prepare for that weekend's hackathon. And my brain was completely fried from the day of coding. My wife was working late, so I checked my calendar to find something to do.</p>
<p>On the first Monday of each month, I would map out all that month's upcoming tech events around southern California, so I'd always have a tech event I could attend if I had the energy.</p>
<p>Ah – tonight is the Santa Barbara Ruby on Rails meetup, and I had already RSVP'd.</p>
<p>I didn't know a lot about Ruby on Rails, but I had completed a few small projects with it. I was much more of a JavaScript and Python developer.</p>
<p>But I figured, what the heck. I need to keep up my momentum with building my network. And the venue was just a few blocks away.</p>
<p>I walked in and it was just a few devs sitting around a table chatting. It quickly became clear that they all worked together at a local startup, maintaining a large Ruby on Rails codebase. Most of them had been working there for several years.</p>
<p>Now at this point, I'd spent the past year building my skills, my network, and my reputation. So I was able to hold my own during the conversation.</p>
<p>But I also had a feel for the limits of my abilities. So I stayed modest. Understated. The way I'd seen so many other successful developers maneuver a conversation at tech events.</p>
<p>It became clear that one of the developers at the table was the Director of Engineering. He reported directly to the CTO.</p>
<p>And then it became clear that they were looking to hire Ruby on Rails developers.</p>
<p>I was candid about my background and my abilities. "My background is in adult education. Teaching English and running schools. I just started learning to code about a year ago."</p>
<p>But the man was surprisingly unfazed. "Well if you want to come in for an interview, we can see whether you'd be a good fit for the team."</p>
<p>That night I walked home feeling an electricity. It was much more dread than excitement.</p>
<p>I felt nowhere near ready. And I wasn't even looking for a job. I was just living off my savings, learning to code full-time, with health insurance through my wife's job.</p>
<p>I was a compulsive saver. People would give me a hard time about it. I would change my own oil, cut my own hair, and even cook my own rice at home when we ordered takeout – just to save a few bucks.</p>
<p>Over the decade that I'd worked as a teacher, I'd managed to save nearly a quarter of my after-tax earnings. And I would buy old video games on Craigslist, then flip them on eBay. That may sound silly, but it was a substantial source of income for me.</p>
<p>What were we saving all this for? We weren't sure. Maybe to buy a house in California at some point in the future? But it meant that I did not have to hustle to get a job. I knew I was in a privileged position, and I tried to make the most of it by learning more every day.</p>
<p>So in short, I didn't think I was ready for my first developer job. And I was worried that if they hired me, it would be a big mistake. They would realize how inexperienced I was, fire me, and then I'd have to explain that failure during future job interviews.</p>
<p>Of course, I now know I was looking at this opportunity the wrong way. But let me finish the story.</p>
<p>When I scheduled my job interview, they asked me for a résumé. I wasn't sure what to do, so I left all my professional experience there. All the schools I'd worked for over the years. (I left off my time running the drive-thru at Taco Bell.) </p>
<p>Of course, none of my work experience had anything to do with coding. But what was I supposed to do, hand them a blank sheet of paper?</p>
<p>Well, I did have an online portfolio of projects I'd built. And most importantly, I had a list of all the hackathons I'd won or placed at. So I included those.</p>
<p>I spent the final hours before the interview revisiting all the Ruby on Rails tutorials I'd used over the past year, to refresh my memory. And then I put on my hoody, jeans, and backpack, and walked over to their office.</p>
<p>The office manager was a nice lady who took me back to the developer bullpen and introduced me to their small team of devs. There were maybe a dozen of them, most of them dressed in jeans and hoodies, aged from early 20s to late 40s. Two of them were women.</p>
<p>I took turns navigating the tangle of desks and cables, shaking hands with each of them and introducing myself. This is where all my experience as a classroom teacher memorizing student names came in handy. I was able to remember all their names, so that later in the day when I left I could follow up with each of them: "Great meeting you [name]. I'd be excited to work alongside you."</p>
<p>First I met with the director of engineering. We went into a small office and closed the door. </p>
<p>A whiteboard on the wall was covered in sketches of Unified Modeling Language (UML) diagrams. A rainbow of dry-erase marker laid out the relationships between various servers and services.</p>
<p>I kept glancing at that whiteboard, fearing that he'd send me over to it to solve some coding problems and demonstrate my skills. Maybe the famous fizzbuzz problem? Maybe he'd want me to invert a binary tree?</p>
<p>But he never even mentioned the whiteboard. He just sat there looking intensely at me the whole time.</p>
<p>They were a company of about 50 employees, with lots of venture capital funding, and thousands of paying customers – mostly small businesses. They prided themselves on being pragmatic. At no point did they inquire about what I studied in school, or what kind of work I did in the past. All they really cared about was...</p>
<p>"Look. I know you can code," he said. "You've been coding this whole time, winning hackathons. I checked out some of your portfolio projects. The code quality was OK for someone who's new to coding. So for me, the real question is – can you learn how we do things here? Can you work with the other devs on the team? And most critically: can you get things done?"</p>
<p>I gulped, leaned forward, and mustered all the confidence I could. "Yes," I said. "I believe I can."</p>
<p>And he said, "Good. Good. OK. Go wait in the Pho restaurant downstairs. [The CTO] should be down there in a minute."</p>
<p>So I talked with the CTO over noodles. Mostly listened. I'd learned that people project intelligence onto quiet people. Listening intently not only helps you get smarter – it even makes you look smarter.</p>
<p>And the approach worked. The meeting lasted about an hour. The noodles were tasty. I learned a lot about the company history, and the near-term goals. The CTO said, "OK go back up and talk with [the director of engineering]."</p>
<p>And I did. And he offered me a job.</p>
<p>Now, I want to emphasize. This is not how most people get their first developer job. </p>
<p>You're probably thinking, "Gee, here Quincy is Forest Gumping his way into a developer job that he wasn't even looking for. If only we could all be so lucky."</p>
<p>And that's certainly what it felt like for me at the time. But in the next section, I'm going to explore the relationship between employers and developers. And how me landing that job was less about my skills as an interviewee, and more about the year of coding, networking, and reputation building that preceded it.</p>
<p>This wasn't a cushy job at a big tech company, with all the compensation, benefits, and company bowling alleys. It was a contractor role that paid about the same as I was making as a teacher.</p>
<p>But it was a developer job. A company was paying me to write code.</p>
<p>I was now a professional developer.</p>
<h3 id="heading-what-employers-want">What Employers Want</h3>
<p>Flash forward a decade. I have now been on both sides of the table. I've been interviewed by hiring managers as a developer. I've interviewed developers as a hiring manager.</p>
<p>I've spent many hours on calls with developers who are in the middle of the job search. Some of them have applied to hundreds of jobs and gotten only a few "call-backs" for job interviews.</p>
<p>I've also spent many hours on calls with managers and recruiters, trying to better understand how they hire and what they look for.</p>
<p>I think much of the frustration developers feel about the hiring process comes down to a misunderstanding.</p>
<p>Employers value one thing above all else: predictability.</p>
<p>Which of these candidates do you think an employer would prefer?</p>
<p><strong>X</strong> is a "rockstar" 10x coder who often has flashes of genius. X also has bursts of incredible productivity. But X is often grumpy with colleagues, and often misses deadlines or meetings.</p>
<p><strong>Y</strong> is an OK coder, and has slower but more consistent output. Y gets along fine with colleagues, and rarely misses meetings or deadlines.</p>
<p><strong>Z</strong> is similar to Y in output, and able to get along well with colleagues and meet deadlines. But Z has changed jobs 3 times in the past 3 years.</p>
<p>OK, you can probably guess from everything I've said up to this point: <strong>Y</strong> is the preferred candidate. And that is because employers value predictability above all else.</p>
<p><strong>X</strong> is a trap candidate that some first-time managers may make the mistake of hiring. If you are curious why hiring X would be such a bad idea, read <a target="_blank" href="https://www.freecodecamp.org/news/we-fired-our-top-talent-best-decision-we-ever-made-4c0a99728fde/">We fired our top talent. Best decision we ever made.</a></p>
<p>I only added <strong>Z</strong> to this list to make a point: try not to change jobs too often. </p>
<p>You can increase your income pretty quickly by laddering from employer to employer. You can start applying for new jobs the moment you accept an offer letter. But this will repel many hiring managers.</p>
<p>After all, the rolling stone gathers no moss. You will be in and out of codebases before you have the time to understand how they work.</p>
<p>Consider this: it can take 6 months or longer for a manager to bring a new developer up to speed, to the point where they can be a net positive for the team.</p>
<p>Until that point, the new hire is essentially a drain on company resources, absorbing time and energy from their peers who have to onboard them, help them find their way around a codebase, and fix their bugs.</p>
<h3 id="heading-most-employers-are-risk-averse">Most Employers are Risk Averse</h3>
<p>Let's say a manager hires the wrong developer. Take a moment to think about how bad that can be for the team.</p>
<p>On average, it takes about 3 months to fill a developer position at a company. Employers have to first:</p>
<ul>
<li>get the budget to hire a developer approved by their bosses</li>
<li>create the job description</li>
<li>post the job on job sites and communicate with recruiters</li>
<li>sift through résumés – many of which will be low-effort from candidates who are blindly applying to as many jobs as possible</li>
<li>start the interviewing process, which may involve flying the candidates out to the city and lodging them in a hotel</li>
<li>rounds of interviews involving lots of team members. For some employers, this is a multi-day affair</li>
<li>selecting a final candidate, and negotiating an offer...</li>
<li>which many candidates will not accept anyway</li>
<li>signing contracts and onboarding the employee</li>
<li>giving them access to sensitive internal systems</li>
<li>introducing them to their teammates, and making sure everyone gets along OK</li>
<li>and then months of informal training, when the employee needs to understand a service or a part of a legacy codebase</li>
<li>and finally, steeping them in the team's way of doing things</li>
</ul>
<p>In short – a lot of work.</p>
<p>Now imagine that after doing all that, the new employee says "Hey, I just got a higher offer from this other company. Peace out, yo."</p>
<p>Or imagine that the employee is unreliable, and often shows up hours after the workday has started.</p>
<p>Or imagine that the employee struggles with untreated drug, alcohol, or gambling addiction, anger issues – or just turns out to be a passive aggressive person who undermines the team.</p>
<p>Now you have to start this entire process over again, and search for a new candidate for the position.</p>
<p>Hiring is hard.</p>
<p>So you can see why employers are risk averse. Many of them will pass over seemingly qualified candidates until they find someone whom they feel 99% sure about.</p>
<h3 id="heading-because-employers-are-so-risk-averse-job-seekers-suffer">Because Employers are So Risk Averse, Job Seekers Suffer</h3>
<p>Now if you think hiring is hard, wait until you hear about the job application process. You may already be all-too-familiar with it. But here goes...</p>
<ul>
<li>You have to prepare your résumé or CV. Along the way, you will make decisions which you'll constantly second-guess throughout your job search.</li>
<li>You have to look around for job openings online, research the employers, and assess whether they're likely to be a good fit for you.</li>
<li>Most job openings will lead to webforms where you will have to retype your résumé over and over again, hoping the form doesn't crash due to server errors or JavaScript validation errors.</li>
<li>Once you submit these job applications, you have to wait while employer process them. Some employers receive so many applications that they can't manually review them all. (Google alone receives 9,000 applications per day.) Employers will use software to filter through applications. In-house recruiters <a target="_blank" href="https://www.freecodecamp.org/news/you-in-6-seconds-how-to-write-a-resume-that-employers-will-actually-read-fd7757740802/">spend an average of 6 seconds looking at each résumé</a>. Often your application will never even be reviewed by a human. </li>
<li>You will likely never hear anything back from the company. They have little incentive to tell you why they rejected you (they don't want you to file a discrimination lawsuit). If you're lucky, you'll get one of those "We've chosen to pursue other candidates" emails.</li>
<li>And all the time you spend applying for these jobs – potentially hours per week – is mentally exhausting and, of course, unpaid.</li>
</ul>
<p>Wow. So you can see what a nightmare the hiring process is for employers, and especially for job candidates.</p>
<p>But if you stick with it, you can eventually land offers. And when it rains, it pours.</p>
<p>Here's data from one freeCodeCamp contributor's job search over the span of 12 weeks:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/85L921BMzXxKhVySPo9gxWamr5J4QLFJaVEn.png" alt="Image" width="600" height="400" loading="lazy">
<em>Out of 291 applications, he ultimately received 8 offers.</em></p>
<p>And as the offers came in, the starting salary got higher and higher. Note, of course, that this is for a job in San Francisco, one of the most expensive cities in the world. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/bDp3eVv6VQS3Og3ulVpwp6dDylIybdpRczsD.png" alt="Image" width="600" height="400" loading="lazy">
<em>By week 12 his starting salary offers were nearly double what they were in week 2.</em></p>
<p>This developer's rate of getting interviews is quite strong. And his negotiation ability was also strong. You can <a target="_blank" href="https://www.freecodecamp.org/news/5-key-learnings-from-the-post-bootcamp-job-search-9a07468d2331/">read more about his process if you're curious</a>.</p>
<p>But as I've said before, it is much easier to get into a company through the side door.</p>
<p>And that's one of the reasons I wrote this book. I don't want you to keep lining up for the front door at these employers.</p>
<h3 id="heading-if-you-build-your-skills-your-network-and-your-reputation-you-can-bypass-a-lot-of-the-job-application-process">If you Build Your Skills, Your Network, and Your Reputation You Can Bypass a Lot of the Job Application Process.</h3>
<p>Throughout this book, I've been teaching you techniques to increase your likelihood of "lucking" into a job offer.</p>
<blockquote>
<p>"Luck is preparation meeting opportunity. If you hadn't been prepared when the opportunity came along, you wouldn't have been 'lucky.'" – Oprah Winfrey</p>
</blockquote>
<p>This is why throughout this book I've encouraged you to develop all three of these areas at once, and to start thinking about them from day one – well in advance of your job search.</p>
<p>My story of not even looking for a job and landing a job may seem silly. But this happens more often than you might think.</p>
<p>The reality is: learning to code is hard.</p>
<p>But knowing how to code is important.</p>
<p>In every industry – in virtually every company in the world – managers are trying to figure out ways to push their processes to the software layer.</p>
<p>That means developers.</p>
<p>You may hear about big layoffs in tech from time to time. Many of these layoffs affect employees who are not developers. But often a lot of developers do lose their jobs.</p>
<p>Why would companies lay off developers, after spending so much time and money recruiting and training them? Aside from a bankruptcy situation, I don't know the answer to that question. I'm not sure that anyone does.</p>
<p>There's growing evidence that layoffs destroy long-term value within a company. But in practice, many CEOs feel pressure from their investors to do layoffs. And when a several companies do layoffs at around the same time, other CEOs may follow suit.</p>
<p>Still, even with the layoffs, most economists expect the number of developer jobs and other software-related jobs to continue to grow. For example, the US Department of Labor Statistics expects an increase of 15% in developers over the next decade.</p>
<p>The job market may be tight right now, but few people expect this downturn to last.</p>
<p>My hope is that with strong skills, a strong network, and a strong reputation, you'll be able to land a good job despite a challenging job market.</p>
<p>Hopefully one day, it will be easier for employers and skilled employees to find one another – without the long, brutal job application and interviewing process.</p>
<h3 id="heading-what-to-expect-from-the-developer-job-interview-process">What to Expect from the Developer Job Interview Process</h3>
<p>Once you start landing job interviews, you'll get a taste of the dreaded developer job interview process and the notorious coding interview.</p>
<p>A typical interview flow might involve:</p>
<ol>
<li>Taking an online coding assessment of your skills or a "Phone Screen."</li>
<li>And then if you pass that, a second phone- or video call-based technical interview</li>
<li>And then if you pass that, an "onsite" interview where you travel to a company office. These usually involve several interviews with HR, hiring managers, and rank-and-file developers you might work with.</li>
</ol>
<p>Along the way, you'll face questions that test your knowledge of problem solving, algorithms &amp; data structures, debugging, and other skills.</p>
<p>Your interviewers may let you solve these coding problems on a computer in a code editor. But often you'll have to solve them by hand while standing at a whiteboard.</p>
<p>The key thing to remember is that the person interviewing you is not just looking for a correct answer from you. They're also trying to understand how you think. </p>
<p>They want to know: do you understand fundamentals of programming and computer science? Or are you just regurgitating a bunch of solutions you memorized?</p>
<p>Now, practicing algorithms and data structures will go a long way. But you also need to be able to think out loud, and explain your thought process as you write your solutions.</p>
<p>The best way to practice this is to talk out loud to yourself while you code. Or – if you're feeling adventurous – live stream yourself coding.</p>
<p>There are lots of "live coding" streams on Twitch where people "learn in public" by building projects in front of an audience. As a bonus, if you're willing to put yourself out there like this, it will also help you build your reputation as a developer.</p>
<p>Another thing to remember during white board interviews: your interviewer. They're not just sitting there waiting for you to finish. They're with you the entire time, watching you and evaluating you both consciously and unconsciously.</p>
<p>Try to make the interview process as interactive as possible for your interviewer. Smile and make occasional eye contact. Try to judge their body language. Are they relaxed? Are they nodding along as you explain points?</p>
<p>Your interviewer probably knows what they're looking for in your code. So see if you can tease some hints out of them. By making observations or asking open-ended questions out loud to yourself, you may be able to get your interviewer to step in, and feel involved in the process.</p>
<p>You want your interviewer to like you. You want them to be rooting for you, so that they may dismiss some of the shortcomings in your programming skills, or overlook some of the errors you may make in your code.</p>
<p>You are selling yourself as a job candidate. Make sure your interviewer feels like they're getting a good deal.</p>
<p>And this goes the same for any Behavioral Interviews you may have to clear. These interviews are less about your coding ability than your "culture fit." (I wish I could tell you what this means, but every manager will define it in a slightly different way.)</p>
<p>In these Behavioral Interviews, you'll have to convince your interviewer that you have strong communication skills.</p>
<p>It definitely helps to be fluent in the language you're interviewing in, and to know the right jargon. You can pick a lot of this up from regularly listening to tech podcasts, like <a target="_blank" href="https://www.freecodecamp.org/news/tag/podcast/">the freeCodeCamp Podcast</a>.</p>
<p>One big thing your interviewers are trying to establish: are you a cool-headed person who will play well with others? The best way to show this is to be polite, and refrain from using profanity or drifting too far off from the subject at hand.</p>
<p>You do not want to get into a debate over something unrelated, like a sports rivalry. I also recommend not trying to correct your interviewers, even if they say things that you believe to be silly or false.</p>
<p>If you get bad vibes from the company, you don't have to accept their job offer. Employers pass on candidates all the time. And you as a candidate also have the right to pass on an employer. The interview itself is probably not the best time for conflict.</p>
<h3 id="heading-should-i-negotiate-my-salary-at-my-first-developer-job">Should I Negotiate My Salary at My First Developer Job?</h3>
<p>Trying to negotiate your salary upward generally does not hurt as long as you do so politely.</p>
<p>I've written at length on <a target="_blank" href="https://www.freecodecamp.org/news/salary-negotiation-how-not-to-set-a-bunch-of-money-on-fire-605aabbaf84b/">how to negotiate your developer job offer salary</a>.</p>
<p>Essentially, negotiating a higher starting salary comes down to how much leverage you have. </p>
<p>Your employer has work to be done. How badly does your employer need you to work for them? What other options do they have?</p>
<p>And you need income to survive. What other options do you have? What is your backup plan?</p>
<p>If you have a job offer from another employer offering to pay you a certain amount, you can use that as leverage in your salary negation.</p>
<p>If your best backup plan is to go back to school and get a graduate degree... that's not particularly strong leverage, but it's better than nothing. And you could mention it during the salary negotiation process.</p>
<p>Think back to the lengthy hiring process I described earlier. Employers have to go through at least a dozen steps before they can reach the job offer step with candidates. They are probably already planning for you to negotiate, and won't be surprised by it.</p>
<p>Now, if you're in a situation like I was where a company just offers you a job out of the blue, you may feel awkward trying to negotiate. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/92508.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>Smithers from the Simpsons</em></p>
<p>I will admit – in my story time above, when my manager offered me the job, I did not negotiate.</p>
<p>In retrospect, should I have negotiated my compensation? Probably.</p>
<p>Did I have leverage? Probably not much. My backup plan was to just keep competing in hackathons and keep sipping tea and coding at the public library.</p>
<p>I may have been able to negotiate and get a few more bucks an hour. But in the moment they offered me the job, compensation was the last thing on my mind. I was just ecstatic that I was going to be a professional developer.</p>
<p>By the way, once you've worked as a developer at a company for a year or so, you may want to ask for a raise. I've written at length about <a target="_blank" href="https://www.freecodecamp.org/news/youre-underpaid-here-s-how-you-can-get-the-pay-raise-you-deserve-fafcf52956d6/">how to ask for a raise as a developer</a>. But it comes down to the same thing: leverage.</p>
<h3 id="heading-should-you-use-a-recruiter-for-your-developer-job-search">Should You Use a Recruiter for Your Developer Job Search?</h3>
<p>Yes. If you can find a recruiter who will help you land your first developer job, I think you should.</p>
<p>I've written at length about <a target="_blank" href="https://www.freecodecamp.org/news/the-tech-recruiter-red-pill-967dd492560c/">why recruiters are an underrated tool in your toolbox</a>.</p>
<p>Many employers will pay recruiters a finder's fee for sending them high quality job candidates.</p>
<p>Recruiters’ incentives are well-aligned with your own goals as a job seeker:</p>
<ol>
<li>Since they get paid based on your starting salary, they are inclined to help you negotiate as high a starting salary as possible.</li>
<li>The more candidates they place — and the faster they place them — the more money recruiters make. So they’ll want to help you get a job as fast as possible so they can move on to other job seekers.</li>
<li>Since they only get paid if you succeed as an employee (and stay for at least 90 days), they'll try and make sure you’re competent, and a good fit for the company’s culture.</li>
</ol>
<p>This said, if a recruiter asks you to pay them money for anything, that is a red flag.</p>
<p>And not all recruiters are created equal. Do your research before working with a recruiter. Even if they're ultimately getting paid by the employer, you are still investing your time in helping them place you. And time is valuable.</p>
<p>Speaking of time, one way you can start getting paid to code sooner – even while you're preparing for the job search – is to get some freelance clients.</p>
<h3 id="heading-how-to-get-freelance-clients">How to Get Freelance Clients</h3>
<p>I encourage new developers to try and get some freelance clients before they start their job search. There are three good reasons for this:</p>
<ol>
<li>It's much easier to get a freelance client than it is to get a full time job.</li>
<li>Freelance work is less risky since you can do it without quitting your day job.</li>
<li>You can start getting paid to code sooner, and start building your portfolio of professional work sooner.</li>
</ol>
<p>Getting freelance clients can be much easier than getting a developer job. Why is this?</p>
<p>Think about small local businesses. It may just be a family that runs a restaurant. Or a shop. Or a plumbing company. Or a law firm.</p>
<p>How many of those businesses could benefit from having an interactive website, back office management systems, and tools to automate their common workflows? Most of them.</p>
<p>Now how many of those companies can afford to have a full-time software developer to build and maintain those systems? Not as many.</p>
<p>That's where freelancers come in. They can do work in a more economical, case-by-case basis. A small business can bring on a freelancer for a single project, or for a shorter period of time.</p>
<p>If you are actively building your network, some of the people you meet may become your clients.</p>
<p>For example, you may meet a local accountant who wants to update their website. And maybe add the ability to schedule a consultation, or accept a credit card payment for a bill. These are common features that small businesses may request, and you may get pretty good at implementing them.</p>
<p>You may also meet the managers of small businesses who need an ERP system, or a CRM system, or an inventory system, or one of countless other tools. </p>
<p>In many cases, there is an open source tool that you can deploy and configure for them. Then you can just teach them how to use that system. And you can bill them a monthly service fee to have you "on call" and ready to fix problems that may arise.</p>
<h3 id="heading-should-i-use-a-contract-for-freelance-work">Should I Use a Contract for Freelance Work?</h3>
<p>You will want to find a standard contract template, customize it, and get a lawyer to approve it.</p>
<p>It may feel awkward to make the local bakery sign a contract with you just to help update their website or social media presence. But doing so will make the entire transaction feel more professional than a mere handshake agreement.</p>
<p>It's unlikely that a small business will take you to court over a few thousand dollars. But in the event that this happens, you'll be glad you signed a contract.</p>
<h3 id="heading-how-much-should-i-charge-for-freelance-work">How Much Should I Charge for Freelance Work?</h3>
<p>I would take whatever you make at your day job, figure out your hourly rate, and double it. This may sound like a lot of money, but freelance work is much harder than regular work. You have to learn a lot.</p>
<p>Alternatively, you could just bill for a project. "I will deploy and configure this system for you for $1,000."</p>
<p>Just be sure to specify a time frame that you are willing to maintain the project. You don't want people calling you 3 years later expecting you to come back and fix a system that nobody has been maintaining.</p>
<h3 id="heading-how-do-i-make-sure-freelance-clients-pay-me">How Do I Make Sure Freelance Clients Pay Me?</h3>
<p>A lot of other freelancers – myself included – use this simple approach: ask for half of your compensation up-front, before you start the work. And when you can demonstrate that you're half way finished, ask for the other half.</p>
<p>Always try to get all the money before you actually finish the project. That way, the client will not be able to dangle the money over your head and try to get extra work out of you.</p>
<p>If you're already paid in full, the work you do to help your client after the fact will convey: "I'm going above and beyond for you."</p>
<p>Which is a totally different vibe from: "Uh oh – are you even going to pay me for all this work I'm doing?"</p>
<h3 id="heading-should-i-use-a-freelance-website-like-upwork-or-fiverr">Should I Use a Freelance Website like Upwork or Fiverr?</h3>
<p>If you are in a rural part of the world and can't find any clients locally, you could try some of these freelance websites. But otherwise I would not focus on them. Here's why:</p>
<p>When you try to land contracts on a freelance website, you are competing with all the freelancers around the world. Many of them will live in cities that have a much lower cost of living than yours. Some of them will not even really care about their reputations like you do, and may be willing to deliver sub-par work.</p>
<p>To some extent, these websites promote a "race to the bottom" phenomenon where the person who offers to do the work the cheapest usually gets the job.</p>
<p>If you instead focus on finding clients through your own local network, you will not have to compete with these freelancers abroad.</p>
<p>And the same goes for people who are looking for help from freelance developers. If you ever want to hire a freelancer, I strongly recommend working with someone you can meet with in-person, who has ties to your community.</p>
<p>Someone who has lived in your city for several years, and attends a lot of the same social gatherings as you – they're going to be much less likely to try to take advantage of you. If both you and your counterparty care about their reputation, you are both invested in a partnership that works. </p>
<p>You can each be a success story in one another's portfolios.</p>
<h3 id="heading-freelancing-is-like-running-a-one-person-company-and-that-means-a-lot-of-hidden-work">Freelancing is like running a one-person company. And that means a lot of hidden work.</h3>
<p>Don't underestimate the amount of "hidden work" involved in running your freelance development practice.</p>
<p>For one, you may want to create your own legal entity.</p>
<p>In the US, the most common approach is to create a Limited Liability Company (LLC) and conduct business as that company – even if you're the only person working there.</p>
<p>This can simplify your taxes. And heaven forbid you make a mistake and get sued by a client, your legal entity can help insulate you from personal liability, so that it's your LLC going into bankruptcy – not you personally.</p>
<p>You may also consider getting liability insurance to further protect against this.</p>
<p>Remember that when you are working freelance, you usually have to pay tax at the end of the year, so be sure to save for this.</p>
<p>To create your LLC, you can of course just find boilerplate paperwork online, and file it yourself. But if you're serious about freelancing, I recommend talking with a small business lawyer and/or accountant to make sure you set everything up correctly.</p>
<h3 id="heading-when-should-i-stop-freelancing-and-start-looking-for-a-job">When Should I Stop Freelancing and Start Looking for a Job?</h3>
<p>If you are able to pay your bills freelancing, you may just want to keep doing it. Over time, you may even be able to build up your own software development agency, and hire other developers to help you.</p>
<p>This said, if you are yearning for the stability of a developer job, you may be in luck. Freelance clients may convert into full-time jobs if you stick with them long enough. At some point, it may make economic sense for a client to just offer you a full-time job at a lower hourly rate. You get the stability of a 40-hour work week, and they get your skills full-time.</p>
<p>You may also be able to hang onto a few freelance clients when you get a job. This can be a nice supplement to your income. But keep in mind that, as we'll learn in the next chapter, your first developer job can be an all-consuming responsibility. At least at first.</p>
<p>How wild is that first year of working as a professional developer going to be? Well, let's talk about that.</p>
<h2 id="heading-chapter-5-how-to-succeed-in-your-first-developer-job">Chapter 5: How to Succeed in Your First Developer Job</h2>
<blockquote>
<p>"A ship in port is safe. But that's not what ships are built for." – Grace Hopper, Mathematician, US Navy Rear Admiral, and Computer Science Pioneer</p>
</blockquote>
<p>Once you get your first developer job, that's when the real learning begins.</p>
<p>You'll learn how to work productively alongside other developers.</p>
<p>You'll learn how to navigate large legacy codebases.</p>
<p>You'll learn Version Control Systems, Continuous Integration and Continuous Delivery tools (CI/CD), project management tools, and more.</p>
<p>You'll learn how to work under an engineering manager. How to ship ahead of a deadline. And how to work through a great deal of ambiguity on the job.</p>
<p>Most importantly, you'll learn how to manage yourself.</p>
<p>You'll learn how to break through psychological barriers that affect all of us, such as imposter syndrome. You'll learn your limits, and how to push ever so slightly beyond them.</p>
<h3 id="heading-story-time-how-did-a-teacher-in-his-30s-succeed-in-his-first-developer-job">Story Time: How did a Teacher in his 30s Succeed in his First Developer Job?</h3>
<p><em>Last time on Story Time: Quincy landed his first developer job at a local tech startup. He was going to work as one of a dozen developers maintaining a large, sophisticated codebase. And he had no idea what he was doing...</em></p>
<p>I woke up at 4 a.m. and I couldn't go back to sleep. I tried. But I had this burning in my chest. This anxiety. Panic.</p>
<p>I had worked for a decade in education. First as a tutor. Then as a teacher. And then as a school director.</p>
<p>In a few hours, I would be starting over from the very bottom, working as a developer.</p>
<p>Would any of my past learnings – past success – even matter in this new career?</p>
<p>I did what I always do when I feel anxiety – I went for a run. I bounded down the hills, my headlamp bobbing in the darkness. When I reached the beach, I ran alongside the ocean as the sun crept up over the treetops.</p>
<p>By the time I got home, my wife was already leaving for work. She told me not to worry. She said, "I'll still love you even if you get fired for not knowing what you're doing."</p>
<p>When I reached my new office, nobody was there. As a teacher, I was used to getting to school at 7:30 sharp. But I quickly realized that most software developers don't start work that early.</p>
<p>So I sat crosslegged in the entry hallway, coding along to tutorials on my netbook.</p>
<p>An employee walked up to me with a nervous look on her face. She probably thought I was a squatter. But I reassured her that I did indeed now work at her company, and convinced her to let me in.</p>
<p>It felt surreal walking across the empty open-plan office toward the developer bullpen, with only the light of the exit sign to guide my way.</p>
<p>I set up my netbook on an empty standing desk and finished my coding tutorial.</p>
<p>A little while later, the lights flickered on around me. My boss had arrived. At first he didn't acknowledge my presence. He just sat down at his desk and started firing off bursts of keystrokes onto his mechanical keyboard.</p>
<p>"Larson," he finally said. "You ready for your big first day?"</p>
<p>I wasn't. But I wanted to signal confidence. So I said the words first uttered in Big Trouble in Little China, one of my favorite 80s movies: "I was born ready."</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/big-trubs-born-ready.jpeg" alt="Image" width="600" height="400" loading="lazy">
<em>You've probably heard "I was born ready" a million times. But it was first uttered in 1986 by Jack Burton to his friend Wang Chi, when they were getting ready to confront a thousand year old wizard in his death warehouse. I can't believe my parents let me watch this back then, but I'm glad they did.</em></p>
<p>"Great," my boss said. "Let's get you a machine."</p>
<p>"Oh, I've already got one," I said, tapping my $200 netbook. "This baby is running Linux Mint, and I've already customized my .emacs file to be able to..."</p>
<p>"We're a Mac shop," he said walking to a storage closet. He rustled around for a moment and emerged. "Here. It's a 3 year old model, but it should do. We wiped it to factory default."</p>
<p>I started to say that I was already familiar with my setup, and that I could work much faster with it, but he would have none of it.</p>
<p>"We're all using the same tools. It makes collaborating a lot easier. Convention over configuration, you know."</p>
<p>That was the first time I'd heard the phrase "convention over configuration" but it would come up a lot over the next few days.</p>
<p>I spent the next few hours configuring my new work computer as other developers gradually filed in.</p>
<p>It was nearly 10 a.m. when we started our team "standup meeting." We all stood in a circle by the whiteboard. We took turns reporting what we were working on that day.</p>
<p>Everyone gave quick, precise status updates.</p>
<p>When it was my turn, I started to introduce myself. I was already anxious enough, when in walked none other than Mike, that ultramarathoner guy who ran the Santa Barbara Startup events. He was crunching on some baby carrots, having already run about 30 miles that morning.</p>
<p>After I finished, Mike spoke, welcoming me and saying he'd seen me at some of his events. He then gave a 15 second status update about some feature he was working on.</p>
<p>The entire meeting only took about 10 minutes, and everyone scattered back to their desks.</p>
<p>I eventually got the company's codebase to run on my new laptop. It was a Ruby on Rails app that had grown over 5 years. I ran the <code>rake stats</code> command and saw that it was millions of lines of code. I shuddered. How could I ever comprehend all that?</p>
<p>My neighbor, a gruff, bearded dev said, "Eh, most of that is just packages. The actual codebase you'll be working on is only maybe 100,000 lines. Don't worry. You'll get the hang of it."</p>
<p>I gulped, but thought to myself: "That's less than millions of lines. So that is good."</p>
<p>"Name's Nick by the way," he said, introducing himself. "If you need any help just let me know. I've been stumbling around this codebase for quite a few years now, so I should be able to help you out."</p>
<p>Over the next few days, I peppered Nick with questions about every internal system I encountered.</p>
<p>Eventually Nick started setting his chat status to "code mode" and putting on his noise cancelling headphones. He swiveled his back toward me a bit, with the body language of: "leave me alone so I can get some of my own work done, too."</p>
<p>This was one of my earliest lessons about team dynamics. You don't want to wear out your welcome with too many questions. You need to get better at learning things for yourself.</p>
<p>But this was a massive codebase, and it was largely undocumented, aside from inline comments and a pretty sparse team wiki.</p>
<p>Since it was a closed-source codebase that only the devs around me were working in, I couldn't use Stack Overflow to figure out where particular logic was located. I just had to feel around in the dark.</p>
<p>I started rotating through which neighbor I'd bug about a particular question. But it felt like I was quickly ringing out any enthusiasm they may have had left for me as a teammate.</p>
<p>I over-corrected. I became shy about asking even simple questions. I made a rule for myself that I would try for 2 hours to get unstuck before I would ask for help.</p>
<p>At some point, after thrashing for several hours, I did ask for help. When my manager discovered I'd been stuck all morning, he asked, "Why didn't you ask for help earlier?"</p>
<p>Another struggle was with understanding the codebase itself – the "monolith" and its many microservices.</p>
<p>The codebase had thousands of unit tests and integration tests. Whenever you wrote a new code contribution, you were also supposed to write tests. These tests helped ensure that your code did what it was supposed to – and didn't break any existing functionality.</p>
<p>I would frequently "break the build" by committing code that I thought was sufficiently tested – only to have my code break some other part of the app I hadn't thought about. This frustrated the entire team, who were unable to merge their own code until the root problem had been fixed.</p>
<p>The build would break several times a week. And I was not the only person who made these sorts of mistakes. But it <strong>felt</strong> like I was.</p>
<p>There were days where I felt like I was not cut out to be a developer. I'd say to myself: "Who am I kidding? I just wake up one day and decide I'm going to be a developer?"</p>
<p>I kept hearing echoes of all those things my developer friends had said to me a year earlier, when I was first starting my coding journey.</p>
<p>"How are you going to hang with people who grew up coding from an early age?"</p>
<p>"You're going to have to drink an entire ocean of knowledge."</p>
<p>"Why don't you just stick with what you're good at?"</p>
<p>I would take progressively longer breaks to get away from my computer. The office had a kitchen filled with snacks. I would find more excuses to get up to grab a snack. Anything to delay the crushing sense that I had no idea what I was doing.</p>
<p>The first few months were rough. During morning standup meetings, it felt like everyone was moving fast. Closing open bugs and shipping features. It felt like I had nothing to say. I was still working on the same feature as the day before.</p>
<p>Every day when I woke up and got ready for work, I felt dread. "This is going to be the day they fire me."</p>
<p>But then I'd go to work and everyone would be pretty kind, pretty patient. I would ask for help if I was really stuck. I would make <strong>some</strong> progress, and maybe fix a bug or two.</p>
<p>I was getting faster at navigating the codebase. I was getting faster at reading stack traces when my code errored out. I was shipping features at a faster clip than before.</p>
<p>Whenever my boss called me into his office, I would think to myself: "Oh no, I was right. I'm going to get fired today." But he would just assign me some more bugs to fix, or features to develop. Phew.</p>
<p>It was the most surreal thing – me terrified out of my mind that I'm about to get the axe, and him having no idea anything's wrong.</p>
<p>Of course, I had heard the term "imposter syndrome" before. But I didn't realize that was what I was experiencing. Surely I was just suffering from "sucks at coding" syndrome, right?</p>
<p>One day I was sitting next to Nick, and he was looking pretty frazzled. I offered to grab him a soda from the kitchen.</p>
<p>When I got back, he cracked the can open, took a sip, and leaned back in his chair, gazing at his monitor full of code. "This bug, man. Three weeks trying to fix this one bug. At this point I'm debugging it in my sleep."</p>
<p>"Three weeks trying to fix the same bug?" I asked. I had never heard of such a thing.</p>
<p>"Some bugs are tougher to crack than others. This is one of those really devious ones."</p>
<p>It felt like someone had slapped me across the face with a salmon. I had viewed my job as chunks of work. As though it should take half a day to fix a bug, and if it took longer than that, I was doing something wrong.</p>
<p>But here Nick was – with his computer science degree from University of California and his years of experience working on this same codebase – and he was stumped for three weeks on a single bug.</p>
<p>Maybe I had been too hard on myself. Maybe some of these bugs I'd been fixing were not necessarily "half-day bugs", but were "two- or three-day bugs." Yes, I was inexperienced and slow. But even so, maybe I was holding myself to unrealistic standards.</p>
<p>After all, when we budgeted time for features, sometimes we would have "5-day features" or even "2-week features." We didn't do this for bugs, but they probably varied similarly.</p>
<p>I went home and read more about Imposter Syndrome. And what I read explained away a lot of my anxiety.</p>
<p>Over the coming months, I kept building out features for the codebase. I kept collaborating with my team. It was still hard, brain-busting work. But it was starting to get a little bit easier.</p>
<p>I bonded with my teammates each day at lunch over board games. One week, we had a company-wide chess tournament. </p>
<p>A couple rounds in, I played against the CEO.</p>
<p>The CEO has an unorthodox chess play style. He used a silly opening that few serious chess players would opt for. And I was able to take any early lead in the game.</p>
<p>But over the next few moves, he was able to slowly grind back control over the game. He eventually gained the upper hand and beat me.</p>
<p>When I asked him how he found time to keep his chess skills sharp while running a company, he said, "Oh, I don't. I only play once or twice a year."</p>
<p>Then he paused for a moment, his hand frozen in front of him, as if preparing to launch into a lecture. He said: "My uncle was a competitive chess player. And he just gave me a single piece of advice to follow: <strong>every time your opponent moves, slow down and try to understand the game from their perspective – why did they make that move?</strong>"</p>
<p>He bowed then excused himself to run to a meeting.</p>
<p>I've thought a lot about what he said over the years. And I've realized this advice doesn't just apply to chess. You can apply it to any adversarial situation.</p>
<h3 id="heading-if-you-keep-having-to-do-a-task-you-should-automate-it">If You Keep Having to Do a Task, You Should Automate it</h3>
<p>Another lesson I learned about software development: since I was the most junior person on the team, I often got assigned the "grunt work" that nobody else wanted to do. One of these tasks was to be the "build nanny."</p>
<p>Whenever someone broke the build, I would pull down the latest version of our main branch and use <code>git bisect</code> to try and identify the commit that broke it.</p>
<p>I'd open up that commit, run the tests, and figure out what went wrong. Then I'd send a message to the person who broke the build, telling them what they needed to fix.</p>
<p>I got really fast at doing this. In a day full of confusing bug reports and ambiguous feature requests, I looked forward to the build breaking. It would give me a chance to feel useful real quick.</p>
<p>It wasn't long before someone on the team said, "With how often the build breaks, we should just automate this."</p>
<p>I didn't say anything, but I felt defensive. This was a bad idea. How could a script do as good a job at finding the guilty commit as I – a flesh and blood developer – could?</p>
<p>It took a few days. But sure enough, one of my teammates whipped up a script. And I didn't have to be the build nanny anymore.</p>
<p>It felt strange to see a message that the build failed, and then a moment later see a message saying which commit broke the build and who needed to go fix it.</p>
<p>I felt indignant. I didn't say anything, but in my mind I was thinking: "That's supposed to be my work. That script took my job."</p>
<p>But of course, I now look back at my reaction and laugh. I imagine myself, now in my 40s, still dropping everything several times each week so I could be the build nanny.</p>
<p>Because in practice, if a task can be automated – if you can break it down into discrete steps that a computer can reliably do for you – then you should probably automate it.</p>
<p>There's plenty of more interesting work you can do with your time.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/01/is_it_worth_the_time_2x-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>This chart from XKCD can help you figure out whether a task is worth the time investment to automate.</em></p>
<h3 id="heading-lessons-from-the-village-elders">Lessons from the Village Elders</h3>
<p>I learned a lot from other people on the team. I learned product design concepts from Mike. He took me running on the beach, and taught me how to run on my forefoot, where the balls of my feet hit the ground before my heels. This is a bit easier on your joints.</p>
<p>And I learned about agile software engineering concepts from Nick. He helped me pick out some good software development books from the company library. And he even invited me over for a house-warming party, and I got to meet his kids.</p>
<p>After about a year of working for the company, I felt it was time to try to strike out on my own, and build some projects around online learning. I sat down with the CTO to break the news to him that I was leaving.</p>
<p>I said, "I'm grateful that you all hired me, even though I was clearly the weakest developer at the company."</p>
<p>He just let out a laugh and said, "Sure, when you started, you were the worst developer on the team. I'd say you're still the worst developer on the team."</p>
<p>I sat there smiling awkwardly, blinking at him, not sure whether he was just angry I was leaving.</p>
<p>And then he said, "But that's smart. You're smart. Because <strong>you always want to be the worst musician in the band</strong>. You always want to be surrounded by people who are better than you. That's how you grow."</p>
<p>Two weeks later, I checked in my code changes for the day and handed off my open tickets. I reset my Mac to factory settings and handed it to my manager.</p>
<p>I shook hands with my teammates and headed out the door into the California evening air.</p>
<p>I hit the ground running, lining up freelance contracts to keep the lights on. And I scouted out an apartment in the Bay Area, just across the bridge from the beating heart of tech in South of Market San Francisco.</p>
<p>I was now a professional developer with a year of experience already under my belt.</p>
<p>I was ready to dream new dreams and make new moves.</p>
<p>I was off to the land of startups.</p>
<h3 id="heading-lessons-from-my-first-year-as-a-developer">Lessons From my First Year as a Developer</h3>
<p>I did a lot of things right during my first year as a professional developer. I give myself a B-.</p>
<p>But if I had the chance to do it all again, there are some things I'd do differently.</p>
<p>Here are some tips. May these maximize your learning and minimize your heartache.</p>
<h4 id="heading-leave-your-ego-at-the-door">Leave Your Ego at the Door</h4>
<p>Many people entering the software development field will start at the very bottom. One title you might have is "Junior Developer."</p>
<p>It can feel a bit awkward to be middle aged and have the word "junior" in your title. But with some patience and some hard work, you can move past it.</p>
<p>One problem I faced every day was – I had 10 years of professional experience. I was not an entry-level employee. Yes, I was new to development, but I was quite experienced at teaching and even managing people. (I'd managed 30 employees at my most recent teaching job.)</p>
<p>And yet – in spite of all my past work experience – I was still an entry-level developer. I was still a novice. A neophyte. A newbie.</p>
<p>As much as I wanted to scream "I used to be the boss – I don't need you to babysit me" – the truth was I did need babysitters.</p>
<p>What if I accidentally broke production? What if I introduced a security vulnerability into the app? What if I wiped the entire database? Or encrypted something important and lost the key?</p>
<p>These sorts of disasters happen all the time.</p>
<p>The reality is as a new developer, you are like a bull in a China shop, trying to walk carefully, but smashing everything in your path.</p>
<p>Don't let yourself get impatient with your teammates. Resist the temptation to talk about your advanced degrees, awards your work has won, or that time the mayor gave you the key to the city. (OK, maybe that last one never happened to me.)</p>
<p>Not just because it will make you hard to work with. Because it will distract you from the task at hand.</p>
<p>For the first few months of my developer career, I used my past accomplishments as a sort of pacifier. "Yeah I suck at coding, but I'm phenomenal at teaching English grammar. Did I mention I used to run a school?"</p>
<p>When your fingers are on the keyboard, and your eyes are on the code editor, you have to let that past self go. You can revel in yesterday's accomplishment tonight, after today's work is done.</p>
<p>But for now, you need to accept all the emotions that come with being a beginner again. You need to focus on the task at hand and get the job done.</p>
<h3 id="heading-its-probably-just-the-imposter-syndrome-talking">It's Probably Just the Imposter Syndrome Talking</h3>
<p>Almost everyone I know has experienced Imposter Syndrome. That feeling that you do not belong. That feeling that at any moment your teammates are going to see how terrible your code is and expose you as not a "real developer."</p>
<p>To some extent, the feeling does not go away. It's always there in the back of your mind, ready to rear its head when you try to do something new.</p>
<p>"Could you help me get past this error message?" "Um... I'm not sure if I'm the best person to ask."</p>
<p>"Could you pair program with me on implementing this feature?" "Um... I guess if you can't find someone more qualified."</p>
<p>"Could you give a talk at our upcoming conference?" "Um... me?"</p>
<p>I've met senior engineers who still suffer from occasional imposter syndrome, more than a decade into their career.</p>
<p>When you feel inadequate or unprepared, it may just be imposter syndrome.</p>
<p>Sure – if you handed me a scalpel and said, "help me perform heart surgery" I would feel like an imposter. To some extent, feeling out of your depth is totally reasonable if you are indeed out of your depth.</p>
<p>The problem is that if you've been practicing software development, you may be able to do something but still inexplicably suffer from anxiety.</p>
<p>I am not a doctor. But my instinct is that – for most people – imposter syndrome will gradually diminish with time, as you get more practice and build more confidence.</p>
<p>But it can randomly pop up. I'm not afraid to admit that I sometimes feel pangs of imposter syndrome when doing a new task, or one I haven't done in a while.</p>
<p>The key is to just accept it: "It's probably just the imposter syndrome talking."</p>
<p>And to keep going.</p>
<h3 id="heading-find-your-tribe-but-dont-fall-for-tribalism">Find Your Tribe. But Don't Fall for Tribalism</h3>
<p>When you get your first developer job, you'll work alongside other developers. Yipee – you found your tribe.</p>
<p>You'll spend a lot of time with them, and you all may start to feel like a tight unit.</p>
<p>But don't ignore the non-developer people around you.</p>
<p>In my story above, I talked about Mike, the Product Manager who also ran startup events. He was "non-technical". His knowledge of coding was limited at best. But I'd venture to say I learned as much from him as anyone else at the company.</p>
<p>You may work with other people from other departments – designers, product managers, project managers, IT people, QA people, marketers, even finance and accounting folks. You can learn a lot from these people, too.</p>
<p>Yes, you should focus on building strong connective tissue between you and the other devs on the team. But stay curious. Hang out with other people in the lunch room or at company events. You never know who's going to be the next person to help you build your skills, your network, or your reputation.</p>
<h3 id="heading-dont-get-too-comfortable-and-specialize-too-early">Don't Get Too Comfortable and Specialize too Early</h3>
<p>I often give this advice to folks who are first starting their coding journey: "learn general coding skills (JavaScript, SQL, Linux, and so on) and then specialize on the job."</p>
<p>The idea is, once you understand how the most common tools work, you can the go and learn those tools' less common equivalents.</p>
<p>For example, once you've learned PostgreSQL, you can easily learn MySQL. Once you've learned Node.js, you can easily learn Ruby on Rails or Java Spring Boot.</p>
<p>But some people specialize too early at work. Their boss might ask them to "own" a certain API or feature. And if they do a good job with that, their boss may keep giving them similar projects.</p>
<p>You are only managing yourself, but your boss is managing many people. They may be too busy to develop a nuanced understanding of your abilities and interests. They may come to see you as "the XYZ person" and just give you tasks related to that.</p>
<p>But you know what you're good at, and what you're interested in. You can try and volunteer for projects outside of your comfort zone. If you can get your boss to assign these to you, you'll be able to continue to expand your skills, and potentially work with new teams.</p>
<p>Remember: your boss may be responsible for your performance at your job, but you are responsible for your performance across your career.</p>
<p>Take on projects that both fulfill your obligation to your employer, and also position you well for your long-term career goals.</p>
<h2 id="heading-epilogue-you-can-do-this">Epilogue: You Can Do This</h2>
<p>If there's one message I want to leave you with here, it is this: <strong>you can do this.</strong></p>
<p>You <strong>can</strong> learn these concepts. </p>
<p>You <strong>can</strong> learn these tools. </p>
<p>You <strong>can</strong> become a developer.</p>
<p>Then, the moment someone hands you money for you to help them code something, you will graduate to being a professional developer.</p>
<p>Learning to code and getting a first developer job is a daunting process. But do not be daunted.</p>
<p>If you stick with it, you will eventually succeed. It is just a matter of practice.</p>
<p>Build your projects. Show them to your friends. Build projects for your friends.</p>
<p>Build your network. Help the people you meet along the way. What goes around comes around. You'll get what's coming to you.</p>
<p>It is not too late. Life is long. </p>
<p>You will look back on this moment years from now and be glad you made a move.</p>
<p>Plan for it to take a long time. Plan for uncertainty.</p>
<p>But above all, keep coming back to the keyboard. Keep making it out to events. Keep sharing your wins with friends.</p>
<p>As Lao Tsu, the Old Master, once said:</p>
<blockquote>
<p>"A journey of a thousand miles begins with a single step."</p>
</blockquote>
<p>By finishing this book, you've already taken a step. Heck, you may have already taken many steps toward your goals.</p>
<p>Momentum is everything. So keep up that forward momentum you've already built up over these past few hours with this book.</p>
<p>Start coding your next project today.</p>
<p>And always remember:</p>
<p>You can do this.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Applied Data Science with Python – Business Intelligence for Developers [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ In the high-stakes game of modern business, data isn't just an asset – it's the power you need to outpace your competition. But as a developer, you know that turning raw data into actionable insights can be a frustrating battle.   Imagine having the ... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/applied-data-science-with-python-book/</link>
                <guid isPermaLink="false">66b99ae361d5a3c241ef5213</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ BUSINESS INTELLIGENCE  ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Data Science ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Python ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Vahe Aslanyan ]]>
                </dc:creator>
                <pubDate>Tue, 04 Jun 2024 17:14:03 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/06/Applied-Data-Science-with-Python-Cover-Version-2--1-.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>In the high-stakes game of modern business, data isn't just an asset – it's the power you need to outpace your competition. But as a developer, you know that turning raw data into actionable insights can be a frustrating battle.  </p>
<p>Imagine having the power to effortlessly transform raw data into a competitive weapon, predicting customer behavior, optimizing operations, and driving your business forward. This is the power of business intelligence, and Python is your key to tapping into it.</p>
<p>This book isn't just about Python – it's about empowering you to become a data expert, equipped with the skills to streamline your workflow, gain a competitive edge in the job market, and become an indispensable asset to your team.</p>
<p>I'll help equip you with the practical skills and knowledge to leverage Python for impactful business analysis. You'll start by building a solid foundation in the core elements of Python programming, learning the syntax, data types, functions, and control structures necessary to effectively manipulate and analyze data.</p>
<p>From there, you'll dive into the essential tools of the data trade: Pandas, NumPy, and Matplotlib. Master these industry-standard libraries to efficiently clean, transform, analyze, and visualize data, unlocking hidden insights and patterns within your datasets.</p>
<p>But this book goes beyond theory. You'll apply your newfound skills to real-world business scenarios through hands-on exercises and case studies, gaining confidence and practical experience. </p>
<p>You'll delve into the core principles of data analysis, exploring techniques from basic statistics and data cleaning to advanced transformations and exploratory data analysis (EDA). This will empower you to derive meaningful insights from even the most complex datasets.</p>
<p>Finally, you'll showcase your expertise by tackling a comprehensive project using real-world sales data. You'll analyze customer segments, identify key trends, and develop data-driven strategies that can directly enhance your organization's performance.</p>
<p>By the end of this journey, you'll not only possess the technical proficiency to work with data but also the ability to communicate its value effectively. You'll understand how to interpret findings, provide context, and present your insights in a way that resonates with decision-makers across your company.</p>
<p>Whether you're starting your data career or seeking to advance your skills, this book is your indispensable guide. It provides the knowledge and tools you need to transform data into actionable business strategies, making you an invaluable asset to your organization.</p>
<h2 id="heading-heres-what-well-cover">Here's What We'll Cover:</h2>
<h3 id="heading-1-python-foundations-building-blocks-for-data-masteryheading-1-python-foundations-building-blocks-for-data-mastery"><a class="post-section-overview" href="#heading-1-python-foundations-building-blocks-for-data-mastery">1. Python Foundations: Building Blocks for Data Mastery</a></h3>
<ul>
<li><a class="post-section-overview" href="#heading-11-basic-python-syntax"><strong>1.1 Data Types:</strong></a> There are a variety of data types you'll encounter – numbers, strings, booleans, and more – and understanding how to work with them is fundamental.</li>
<li><a class="post-section-overview" href="#heading-12-data-types-and-variables"><strong>1.2 Variables:</strong></a> Data values can be stored and manipulated using variables, a key concept in data analysis.</li>
<li><a class="post-section-overview" href="#heading-13-operators-manipulating-and-comparing-data"><strong>1.3 Functions:</strong></a> Reusable code blocks, or functions, can be created to perform specific tasks, streamlining the analysis process.</li>
<li><a class="post-section-overview" href="#heading-14-control-flow"><strong>1.4 Conditional Statements and Loops:</strong></a> The flow of code can be controlled with <code>if</code> statements, <code>for</code> loops, and <code>while</code> loops.</li>
<li><a class="post-section-overview" href="#heading-15-functions-in-python"><strong>1.5 Functions in Python:</strong></a> Learn how to bundle reusable code blocks, making your programs more organized and efficient.</li>
<li><a class="post-section-overview" href="#heading-16-modules-and-packages"><strong>1.6 Modules and Packages:</strong></a> Tap into a vast collection of pre-built tools and libraries that extend Python's capabilities for data analysis and beyond</li>
<li><a class="post-section-overview" href="#heading-17-error-handling"><strong>1.7 Error Handling:</strong></a> Write code that can gracefully handle unexpected issues, ensuring your programs run smoothly even when things go wrong.</li>
</ul>
<h3 id="heading-2-essential-libraries-your-data-wrangling-dream-teamheading-2-essential-python-libraries-for-data-wrangling"><a class="post-section-overview" href="#heading-2-essential-python-libraries-for-data-wrangling">2. Essential Libraries: Your Data Wrangling Dream Team</a></h3>
<h4 id="heading-21-pandasheading-21-pandas"><a class="post-section-overview" href="#heading-21-pandas">2.1 Pandas:</a></h4>
<ul>
<li><a class="post-section-overview" href="#heading-series-and-dataframes"><strong>2.1.1 Series and DataFrames:</strong></a> These core data structures will become your best friends for organizing and analyzing data.</li>
<li><a class="post-section-overview" href="#heading-data-manipulation"><strong>2.1.2 Data Manipulation:</strong></a> Filtering, sorting, aggregating, and transforming data are essential skills for any data analyst.</li>
<li><a class="post-section-overview" href="#heading-213-data-cleaning"><strong>2.1.3 Data Cleaning:</strong></a> Missing values, outliers, and inconsistencies can be handled effectively with Pandas.</li>
<li><strong><a class="post-section-overview" href="#heading-214-data-exploration">2.1.4 Data Exploration:</a></strong> Pandas functions are invaluable for summarizing data and gaining initial insights.</li>
</ul>
<h4 id="heading-22-numpyheading-22-numpy"><a class="post-section-overview" href="#heading-22-numpy">2.2 NumPy:</a></h4>
<ul>
<li><a class="post-section-overview" href="#heading-221-arrays"><strong>2.2.1 Arrays:</strong></a> Efficient numerical arrays can be used for high-performance calculations.</li>
<li><a class="post-section-overview" href="#heading-222-mathematical-operations"><strong>2.2.2 Mathematical Operations:</strong></a> Calculations on arrays can be performed element-wise or as a whole.</li>
<li><a class="post-section-overview" href="#heading-223-random-number-generation"><strong>2.2.3 Random Number Generation:</strong></a> Datasets can be created for testing or simulations.</li>
</ul>
<h4 id="heading-23-matplotlibheading-23-matplotlib"><a class="post-section-overview" href="#heading-23-matplotlib">2.3 Matplotlib:</a></h4>
<ul>
<li><a class="post-section-overview" href="#heading-231-basic-plots"><strong>2.3.1 Basic Plots:</strong></a> Learn how to create various types of plots, including line charts, scatter plots, bar charts, and histograms.</li>
<li><a class="post-section-overview" href="#heading-232-customization"><strong>2.3.2 Customization:</strong></a> Colors, labels, and styles can be adjusted to create informative and visually appealing plots.</li>
</ul>
<h3 id="heading-3-practical-examples-from-theory-to-actionheading-3-practical-examples-from-theory-to-action"><a class="post-section-overview" href="#heading-3-practical-examples-from-theory-to-action">3. Practical Examples: From Theory to Action</a></h3>
<p>In addition to theory, you'll gain hands-on experience:</p>
<ul>
<li><a class="post-section-overview" href="#heading-31-loading-and-cleaning-data"><strong>3.1 Loading and Cleaning Data:</strong></a> Learn how to import data from CSV files, handle missing values, and standardize data types.</li>
<li><a class="post-section-overview" href="#heading-32-exploring-data-with-pandas"><strong>3.2 Exploring Data with Pandas:</strong></a> Functions like <code>.describe()</code>, <code>.groupby()</code>, and <code>.value_counts()</code> will be used to uncover patterns.</li>
<li><a class="post-section-overview" href="#heading-33-visualizing-trends-with-matplotlib"><strong>3.3 Visualizing Trends with Matplotlib:</strong></a> Create meaningful plots to reveal relationships between variables.</li>
</ul>
<h3 id="heading-4-data-analysis-fundamentals-the-art-of-making-sense-of-dataheading-4-data-analysis-fundamentals-the-art-of-making-sense-of-data"><a class="post-section-overview" href="#heading-4-data-analysis-fundamentals-the-art-of-making-sense-of-data">4. Data Analysis Fundamentals: The Art of Making Sense of Data</a></h3>
<ul>
<li><a class="post-section-overview" href="#heading-41-data-types-and-structures"><strong>4.1 Data Types and Structures:</strong></a> Understanding the difference between categorical and numerical data is crucial for choosing the right analysis techniques.</li>
<li><a class="post-section-overview" href="#heading-42-descriptive-statistics"><strong>4.2 Descriptive Statistics:</strong></a> Central tendency (mean, median, mode) and dispersion (range, variance, standard deviation) can be calculated to summarize data.</li>
<li><a class="post-section-overview" href="#heading-43-data-cleaning-and-preparation"><strong>4.3 Data Cleaning and Preparation:</strong></a> Learn best practices for handling missing values, duplicates, and outliers.</li>
<li><a class="post-section-overview" href="#heading-44-exploratory-data-analysis-eda"><strong>4.4 Exploratory Data Analysis (EDA):</strong></a> Visualization and summary statistics can be used to generate hypotheses and gain deeper insights into the data.</li>
</ul>
<h3 id="heading-5-introduction-to-the-projectheading-5-applied-data-science-project"><a class="post-section-overview" href="#heading-5-applied-data-science-project">5. Introduction to the Project</a></h3>
<ul>
<li><a class="post-section-overview" href="#heading-51-introduction-to-the-project"><strong>5.1</strong> <strong>Project goals:</strong></a> understanding customers, tracking sales patterns, and utilizing data for strategic decisions.</li>
<li><a class="post-section-overview" href="#heading-the-superstore-sales-dataset-a-resource-for-retail-analysis-and-forecasting"><strong>5.1</strong> <strong>Introduction of the Superstore sales dataset</strong> and its features.</a></li>
</ul>
<h3 id="heading-6-code-walkthroughheading-code-walkthrough"><a class="post-section-overview" href="#heading-code-walkthrough">6. Code Walkthrough</a></h3>
<ul>
<li><a class="post-section-overview" href="#heading-data-loading-and-preparation"><strong>6.1</strong> Setup and Data Loading</a></li>
<li><a class="post-section-overview" href="#heading-handling-missing-data"><strong>6.2</strong> Data Cleaning and Preprocessing</a></li>
<li><a class="post-section-overview" href="#heading-exploratory-data-analysis-eda"><strong>6.3</strong> Exploratory Data Analysis (EDA)</a></li>
<li><a class="post-section-overview" href="#heading-customer-segmentation"><strong>6.4</strong> Insight Extraction and Implementation</a></li>
</ul>
<h3 id="heading-7-analyzing-the-resultsheading-analyzing-the-results"><a class="post-section-overview" href="#heading-analyzing-the-results">7. Analyzing The Results</a></h3>
<ul>
<li><a class="post-section-overview" href="#heading-customer-segmentation-1"><strong>7.1</strong> Customer Segmentation</a></li>
<li><a class="post-section-overview" href="#heading-customer-loyalty"><strong>7.2</strong> Customer Loyalty, Shipping, and Geographic Advantage</a></li>
<li><a class="post-section-overview" href="#heading-identifying-and-nurturing-top-spenders"><strong>7.3</strong> Identifying Key Contributors</a></li>
<li><a class="post-section-overview" href="#heading-geographical-analysis"><strong>7.4</strong> Shipping Analysis</a></li>
<li><a class="post-section-overview" href="#heading-product-category-analysis"><strong>7.5</strong> Product Category Analysis</a></li>
<li><a class="post-section-overview" href="#heading-sales-analysis"><strong>7.6</strong> Sales Analysis</a></li>
<li><a class="post-section-overview" href="#heading-total-sales-by-us-state"><strong>7.7</strong> Geographical Mapping</a></li>
</ul>
<h3 id="heading-8-conclusion-and-future-stepsheading-conclusion"><a class="post-section-overview" href="#heading-conclusion">8. Conclusion and Future Steps</a></h3>
<ul>
<li><a class="post-section-overview" href="#heading-empowering-data-driven-decision-making"><strong>8.1</strong> <strong>Summary</strong> of key insights and their implications for business strategy.</a></li>
<li><a class="post-section-overview" href="#heading-optimizing-sales-and-marketing-strategies"><strong>8.2</strong> <strong>Discussion</strong> on the next steps for implementing the findings from the data analysis.</a></li>
<li><a class="post-section-overview" href="#heading-product-analysis-for-strategic-growth"><strong>8.3</strong> <strong>Closing remarks</strong> and an invitation for feedback and further interaction.</a></li>
</ul>
<h2 id="heading-1-python-foundations-building-blocks-for-data-mastery">1. Python Foundations: Building Blocks for Data Mastery</h2>
<p>Having a strong command of the Python programming language is the bedrock upon which your data analysis and business intelligence capabilities will be built. </p>
<p>This chapter serves as a guide to the essential elements of Python, equipping you with the foundational skills necessary to wield data as a strategic asset.</p>
<h3 id="heading-what-well-cover">What We'll Cover:</h3>
<ol>
<li><strong>Understanding Python Syntax</strong>: We'll begin by delving into Python's fundamental syntax, unraveling the language's structure, rules, and best practices. You'll learn how to write clean, readable code that is not only efficient but also easy to maintain and collaborate on.</li>
<li><strong>Working with Data: Types and Variables</strong>: Next, we'll explore the diverse landscape of data types and variables, the essential containers for the information you'll be working with. From numbers and strings to booleans, lists, dictionaries, and sets, you'll gain a deep understanding of how to store, manipulate, and extract meaning from data.</li>
<li><strong>Manipulating Data with Operators</strong>: We'll then turn our attention to Python's powerful operators, the tools that enable you to perform calculations, comparisons, and logical operations on your data. You'll discover how to leverage arithmetic, comparison, logical, and assignment operators to transform and refine your data, preparing it for insightful analysis.</li>
<li><strong>Controlling Program Flow</strong>: Understanding control flow is crucial for creating dynamic and responsive programs. We'll explore conditional statements and loops, the mechanisms that allow you to guide the execution of your code based on specific conditions and iterate over data collections efficiently.</li>
<li><strong>Building Reusable Code with Functions</strong>: Functions are the building blocks of reusable code, and we'll delve into their creation, execution, and versatile applications. You'll learn how to define functions, pass arguments, return values, and even create anonymous functions known as lambda functions, streamlining your data analysis workflows.</li>
</ol>
<h3 id="heading-11-basic-python-syntax">1.1 Basic Python Syntax:</h3>
<h4 id="heading-indentation-pythons-unique-way-of-structuring-code">Indentation: Python's unique way of structuring code</h4>
<p>In Python, indentation is not merely a stylistic choice – it's a fundamental aspect of the language's syntax. </p>
<p>Unlike languages like Java, which use curly braces <code>{}</code> to define code blocks, Python relies on consistent indentation to indicate the grouping of statements.</p>
<p>Why indentation matters:</p>
<ul>
<li><strong>Readability:</strong> Indentation visually delineates code blocks, making it easier to understand the logical structure of your program.</li>
<li><strong>Functionality:</strong> Python uses indentation to determine which statements belong to a particular block, such as those within a loop or conditional statement. Inconsistent indentation can lead to errors and unexpected behavior.</li>
</ul>
<p>Here's a code example:</p>
<p><strong>Bad Indentation:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> x &gt; <span class="hljs-number">5</span>:
    print(<span class="hljs-string">"x is greater than 5"</span>)
  y = x * <span class="hljs-number">2</span>   <span class="hljs-comment"># Incorrect indentation</span>
     print(<span class="hljs-string">"y is"</span>, y) <span class="hljs-comment"># Inconsistent indentation</span>
</code></pre>
<p>In this example, the indented lines under the <code>if</code> statement form a code block. If the condition <code>x &gt; 5</code> is true, all indented statements will execute.</p>
<p><strong>Why it's bad:</strong></p>
<ul>
<li><strong>Error-prone:</strong> The inconsistent indentation will cause a <code>IndentationError</code> when you try to run the code. Python cannot determine which lines are meant to be part of the <code>if</code> block.</li>
<li><strong>Difficult to read:</strong> Even if it ran (by fixing the errors), the uneven indentation makes it hard to quickly grasp the code's logic. It's unclear at a glance which actions depend on the condition <code>x &gt; 5</code>.</li>
</ul>
<p><strong>Good Indentation:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> x &gt; <span class="hljs-number">5</span>:
    print(<span class="hljs-string">"x is greater than 5"</span>)
    y = x * <span class="hljs-number">2</span>
    print(<span class="hljs-string">"y is"</span>, y)
</code></pre>
<p><strong>Why it's good:</strong></p>
<ul>
<li><strong>Clear structure:</strong> The consistent use of four spaces for each level of indentation creates a visual hierarchy that mirrors the code's logic.</li>
<li><strong>Easy to read:</strong>  Anyone reading the code can immediately see that the calculation of <code>y</code> and its subsequent printing are dependent on the value of <code>x</code> being greater than 5.</li>
<li><strong>No errors:</strong>  This code will run without any indentation-related problems.</li>
</ul>
<p>Key points about indentation:</p>
<ul>
<li><strong>Consistency is key:</strong>  Always use the same number of spaces or tabs for each level of indentation.</li>
<li><strong>Follow PEP 8:</strong>  Python's style guide (PEP 8) recommends using four spaces per indentation level. This is a widely accepted convention in the Python community.</li>
<li><strong>Use your editor's tools:</strong> Most code editors have features to automatically indent your code correctly, helping you avoid mistakes.</li>
</ul>
<p>By following these guidelines, you'll write Python code that is not only functional but also clear, readable, and maintainable.</p>
<p><strong>Best Practices:</strong></p>
<ul>
<li><strong>Consistency:</strong>  Choose either spaces or tabs for indentation, and stick with your choice throughout your code. Most Python developers prefer spaces.</li>
<li><strong>Standard Indentation:</strong> The recommended indentation level is four spaces per block.</li>
</ul>
<h4 id="heading-comments-documenting-your-code-for-clarity">Comments: Documenting Your Code for Clarity</h4>
<p>Comments are non-executable lines of text that you add to your Python code to explain its purpose, logic, or any other relevant information. While the Python interpreter ignores comments, they are invaluable for:</p>
<ul>
<li><strong>Understanding:</strong>  Helping you (or others) understand the code's functionality later on.</li>
<li><strong>Debugging:</strong>  Temporarily disabling parts of your code during troubleshooting.</li>
</ul>
<p><strong>Types of Comments:</strong></p>
<ul>
<li><strong>Single-Line Comments:</strong> Start with a hash symbol (#) and continue to the end of the line.</li>
<li><strong>Multi-Line Comments:</strong>  Enclose the comment text within triple quotes (''' or """).</li>
</ul>
<p><strong>Code Example:</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># This is a single-line comment explaining the calculation</span>
result = x + y  

<span class="hljs-string">'''
This is a multi-line comment that provides a detailed explanation 
of the function's purpose, arguments, and return value.
'''</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_average</span>(<span class="hljs-params">numbers</span>):</span>
    ...
</code></pre>
<h4 id="heading-common-errors-and-debugging-troubleshooting-your-python-code">Common Errors and Debugging: Troubleshooting Your Python Code</h4>
<p>As you begin your Python journey, encountering errors is inevitable. Fortunately, Python provides informative error messages to guide you towards solutions.</p>
<p><strong>Common Errors:</strong></p>
<ul>
<li><strong>Syntax Errors:</strong> Occur when your code violates Python's grammatical rules (for example, forgetting a colon, mismatched parentheses).</li>
<li><strong>Indentation Errors:</strong> Result from incorrect or inconsistent indentation.</li>
<li><strong>Name Errors:</strong> Happen when you use a variable or function name that hasn't been defined.</li>
<li><strong>Type Errors:</strong> Occur when you perform an operation on incompatible data types (for example, adding a string and a number).</li>
</ul>
<p><strong>Debugging Tips:</strong></p>
<ul>
<li><strong>Read Error Messages Carefully:</strong> They often pinpoint the type of error and its location in your code.</li>
<li><strong>Print Statements:</strong> Use <code>print()</code> statements to check the values of variables at different points in your code.</li>
<li><strong>Interactive Debugging:</strong> Use tools like <code>pdb</code> (Python Debugger) to step through your code line by line and inspect variables.</li>
<li><strong>Online Resources:</strong>  Search online forums or communities for help with specific errors.</li>
</ul>
<p><strong>Key Takeaways:</strong></p>
<ul>
<li><strong>Indentation:</strong> Mastering indentation is crucial for writing correct and readable Python code.</li>
<li><strong>Comments:</strong>  Document your code thoroughly with comments to make it easier to understand and maintain.</li>
<li><strong>Debugging:</strong>  Don't be afraid of errors! Use them as learning opportunities to improve your coding skills.</li>
</ul>
<h3 id="heading-12-data-types-and-variables">1.2 Data Types and Variables:</h3>
<h4 id="heading-understanding-data-types">Understanding Data Types</h4>
<p>In Python, everything is an object, and each object has a specific data type. Data types determine the kind of values a variable can hold and the operations you can perform on them. </p>
<p>Let's explore the fundamental data types you'll encounter in your data analysis journey:</p>
<p><strong>1. Numbers</strong>:</p>
<ul>
<li>Integers (<code>int</code>): Represent whole numbers (like <code>-3</code>, <code>0</code>, <code>12</code>).</li>
<li>Floating-Point Numbers (<code>float</code>): Represent numbers with decimal points (like <code>3.14</code>, <code>-0.5</code>, <code>1e6</code>).</li>
</ul>
<pre><code class="lang-python">age = <span class="hljs-number">30</span>  <span class="hljs-comment"># integer</span>
price = <span class="hljs-number">19.99</span>  <span class="hljs-comment"># float</span>
</code></pre>
<p><strong>2.</strong> <strong>Strings</strong> (<code>str</code>): Sequences of characters enclosed in single or double quotes (for example, <code>"Hello"</code>, <code>'Python'</code> ).</p>
<pre><code class="lang-python">name = <span class="hljs-string">"Alice"</span>
message = <span class="hljs-string">'Welcome to Python!'</span>
</code></pre>
<p><strong>3.</strong> <strong>Booleans</strong> (<code>bool</code>): Represent logical values, either <code>True</code> or <code>False</code>.</p>
<pre><code class="lang-python">is_student = <span class="hljs-literal">True</span>
is_valid = <span class="hljs-literal">False</span>
</code></pre>
<h4 id="heading-working-with-collections-lists-dictionaries-tuples-and-sets">Working with Collections: Lists, Dictionaries, Tuples, and Sets</h4>
<p>Python offers powerful data structures to handle collections of items:</p>
<p><strong>1. Lists</strong> (<code>list</code>): Ordered, mutable collections of items.</p>
<pre><code class="lang-python">numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>]
names = [<span class="hljs-string">"Alice"</span>, <span class="hljs-string">"Bob"</span>, <span class="hljs-string">"Charlie"</span>]
</code></pre>
<p><strong>2. Dictionaries</strong> (<code>dict</code>): Unordered collections of key-value pairs, where keys are unique.</p>
<pre><code class="lang-python">student = {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">25</span>, <span class="hljs-string">"grades"</span>: [<span class="hljs-number">90</span>, <span class="hljs-number">85</span>, <span class="hljs-number">92</span>]}
</code></pre>
<p><strong>3. Tuples</strong> (<code>tuple</code>): Ordered, immutable collections of items.</p>
<pre><code class="lang-python">coordinates = (<span class="hljs-number">10</span>, <span class="hljs-number">20</span>)
</code></pre>
<p><strong>4. Sets</strong> (<code>set</code>): Unordered collections of unique items.</p>
<pre><code class="lang-python">unique_numbers = {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>}  <span class="hljs-comment"># Will store {1, 2, 3, 4}</span>
</code></pre>
<h4 id="heading-variables-storing-and-manipulating-data">Variables: Storing and Manipulating Data</h4>
<p>Variables are named containers for storing data values. In Python, you create a variable by assigning a value to it using the assignment operator (<code>=</code>).</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python">x = <span class="hljs-number">10</span>      <span class="hljs-comment"># x is an integer variable</span>
name = <span class="hljs-string">"John"</span>  <span class="hljs-comment"># name is a string variable</span>
</code></pre>
<p><strong>Variable Naming Rules:</strong></p>
<ul>
<li>Must start with a letter (a-z, A-Z) or underscore (_).</li>
<li>Can contain letters, numbers, and underscores.</li>
<li>Case-sensitive (<code>myVar</code> and <code>myvar</code> are different variables).</li>
<li>Avoid using reserved keywords (for example, <code>if</code>, <code>for</code>, <code>while</code>).</li>
</ul>
<h4 id="heading-type-conversions-adapting-data-for-different-operations">Type Conversions: Adapting Data for Different Operations</h4>
<p>You can convert values from one data type to another using type conversion functions like <code>int()</code>, <code>float()</code>, <code>str()</code>, <code>bool()</code>, <code>list()</code>, <code>tuple()</code>, <code>set()</code>, and <code>dict()</code>.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-python">x = <span class="hljs-number">10</span>       <span class="hljs-comment"># integer</span>
y = float(x)  <span class="hljs-comment"># convert x to a float</span>
print(y)     <span class="hljs-comment"># Output: 10.0</span>
</code></pre>
<p><strong>Key Takeaways:</strong></p>
<ul>
<li>Understanding Python's data types is essential for effective data manipulation and analysis.</li>
<li>Use appropriate data structures (lists, dictionaries, tuples, sets) to organize your data.</li>
<li>Variables are your tools for storing and manipulating data values.</li>
<li>Type conversions allow you to adapt data for specific operations.</li>
</ul>
<p>With a solid grasp of these concepts, you'll be well-equipped to tackle the challenges of real-world data analysis using Python. The next section will introduce you to Python's operators, providing the means to perform calculations and manipulate your data further.</p>
<h3 id="heading-13-operators-manipulating-and-comparing-data">1.3 Operators: Manipulating and Comparing Data</h3>
<p>Operators are symbols or special characters that perform specific operations on values or variables. In Python, we use operators to manipulate and compare data. </p>
<p>There are four primary types of operators we'll cover in this section:</p>
<h4 id="heading-arithmetic-operators-performing-mathematical-calculations">Arithmetic Operators: Performing Mathematical Calculations</h4>
<p>Arithmetic operators are used for performing basic mathematical operations:</p>
<table><tbody><tr><th>Operator</th><th>Meaning</th><th>Example</th><th>Result</th></tr><tr><td><code>+</code></td><td>Addition</td><td><code>5 + 3</code></td><td><code>8</code></td></tr><tr><td><code>-</code></td><td>Subtraction</td><td><code>5 - 3</code></td><td><code>2</code></td></tr><tr><td><code><em></em></code></td><td>Multiplication</td><td><code>5  3</code></td><td><code>15</code></td></tr><tr><td><code>/</code></td><td>Division</td><td><code>5 / 3</code></td><td><code>1.666</code></td></tr><tr><td><code>//</code></td><td>Floor division</td><td><code>5 // 3</code></td><td><code>1</code></td></tr><tr><td><code>%</code></td><td>Modulus</td><td><code>5 % 3</code></td><td><code>2</code></td></tr><tr><td><code><strong></strong></code></td><td>Exponentiation</td><td><code>5 3</code></td><td><code>125</code></td></tr></tbody></table>

<p><strong>Example in Python:</strong></p>
<pre><code class="lang-python">x = <span class="hljs-number">10</span>
y = <span class="hljs-number">3</span>

sum = x + y          <span class="hljs-comment"># Addition</span>
difference = x - y   <span class="hljs-comment"># Subtraction</span>
product = x * y      <span class="hljs-comment"># Multiplication</span>
quotient = x / y    <span class="hljs-comment"># Division</span>
floor_div = x // y   <span class="hljs-comment"># Floor division</span>
remainder = x % y    <span class="hljs-comment"># Modulus</span>
power = x ** y       <span class="hljs-comment"># Exponentiation</span>
</code></pre>
<h4 id="heading-comparison-operators-evaluating-relationships-between-values">Comparison Operators: Evaluating Relationships Between Values</h4>
<p>Comparison operators are used to compare two values and return a Boolean result (<code>True</code> or <code>False</code>).</p>
<table><tbody><tr><th>Operator</th><th>Meaning</th><th>Example</th><th>Result</th></tr><tr><td><code>==</code></td><td>Equal to</td><td><code>5 == 3</code></td><td><code>False</code></td></tr><tr><td><code>!=</code></td><td>Not equal to</td><td><code>5 != 3</code></td><td><code>True</code></td></tr><tr><td><code>&gt;</code></td><td>Greater than</td><td><code>5 &gt; 3</code></td><td><code>True</code></td></tr><tr><td><code>&lt;</code></td><td>Less than</td><td><code>5 &lt; 3</code></td><td><code>False</code></td></tr><tr><td><code>&gt;=</code></td><td>Greater than or equal to</td><td><code>5 &gt;= 3</code></td><td><code>True</code></td></tr><tr><td><code>&lt;=</code></td><td>Less than or equal to</td><td><code>5 &lt;= 3</code></td><td><code>False</code></td></tr></tbody></table>

<p><strong>Example in Python:</strong></p>
<pre><code class="lang-python">x = <span class="hljs-number">10</span>
y = <span class="hljs-number">3</span>

is_equal = x == y       <span class="hljs-comment"># Equal to</span>
is_not_equal = x != y   <span class="hljs-comment"># Not equal to</span>
is_greater = x &gt; y      <span class="hljs-comment"># Greater than</span>
is_less = x &lt; y         <span class="hljs-comment"># Less than</span>
is_greater_or_equal = x &gt;= y   <span class="hljs-comment"># Greater than or equal to</span>
is_less_or_equal = x &lt;= y      <span class="hljs-comment"># Less than or equal to</span>
</code></pre>
<h4 id="heading-logical-operators-combining-boolean-expressions">Logical Operators: Combining Boolean Expressions</h4>
<p>Logical operators are used to combine multiple Boolean expressions.</p>
<table><tbody><tr><th>Operator</th><th>Meaning</th><th>Example</th><th>Result</th></tr><tr><td><code>and</code></td><td>True if both operands are true</td><td><code>(5 &gt; 3) and (10 &lt; 20)</code></td><td><code>True</code></td></tr><tr><td><code>or</code></td><td>True if at least one operand is true</td><td><code>(5 &gt; 3) or (10 &gt; 20)</code></td><td><code>True</code></td></tr><tr><td><code>not</code></td><td>True if operand is false</td><td><code>not (5 &gt; 3)</code></td><td><code>False</code></td></tr></tbody></table>

<p><strong>Example in Python:</strong></p>
<pre><code class="lang-python">x = <span class="hljs-number">10</span>
y = <span class="hljs-number">3</span>
z = <span class="hljs-number">20</span>

result1 = (x &gt; y) <span class="hljs-keyword">and</span> (z &gt; y)    <span class="hljs-comment"># True</span>
result2 = (x &lt; y) <span class="hljs-keyword">or</span> (z &gt; x)     <span class="hljs-comment"># True</span>
result3 = <span class="hljs-keyword">not</span> (x == y)          <span class="hljs-comment"># True</span>
</code></pre>
<h4 id="heading-assignment-operators-assigning-values-to-variables">Assignment Operators: Assigning Values to Variables</h4>
<p>Assignment operators are used to assign values to variables.</p>
<table><tbody><tr><th>Operator</th><th>Meaning</th><th>Example</th><th>Equivalent to</th></tr><tr><td><code>=</code></td><td>Assign value</td><td><code><span class="citation-0">x = 5</span></code></td><td><code><span class="citation-0">x = 5</span></code></td></tr><tr><td><code><span class="citation-0">+=</span></code></td><td><span class="citation-0">Add and assign</span></td><td><code><span class="citation-0">x += 3</span></code></td><td><code><span class="citation-0">x = x + 3</span></code></td></tr><tr><td><code><span class="citation-0">-=</span></code></td><td><span class="citation-0">Subtract and assign</span></td><td><code><span class="citation-0">x -= 3</span></code></td><td><code><span class="citation-0">x = x - 3</span></code></td></tr><tr><td><code><span class="citation-0"><em>=</em></span></code></td><td><span class="citation-0">Multiply and assign</span></td><td><code><span class="citation-0">x = 3</span></code></td><td><code><span class="citation-0">x = x <em> 3</em></span></code></td></tr><tr><td><code><span class="citation-0">/=</span></code></td><td><span class="citation-0">Divide and assign</span></td><td><code><span class="citation-0">x /= 3</span></code></td><td><code><span class="citation-0">x = x / 3</span></code><span class="citation-0 citation-end-0"></span></td></tr><tr><td><code>//=</code></td><td>Floor divide and assign</td><td><code>x //= 3</code></td><td><code>x = x // 3</code></td></tr><tr><td><code>%=</code></td><td>Modulus and assign</td><td><code>x %= 3</code></td><td><code>x = x % 3</code></td></tr><tr><td><code><strong>=</strong></code></td><td>Exponent and assign</td><td><code>x = 3</code></td><td><code>x = x * 3</code></td></tr></tbody></table>

<p><strong>Example in Python:</strong></p>
<pre><code class="lang-python">x = <span class="hljs-number">10</span>
x += <span class="hljs-number">5</span>   <span class="hljs-comment"># x is now 15</span>
x *= <span class="hljs-number">2</span>   <span class="hljs-comment"># x is now 30</span>
</code></pre>
<p>Here is some more comprehensive code to show combination of arithmetic, comparison, logical, and assignment operators. </p>
<pre><code class="lang-python"><span class="hljs-comment"># Initialize variables with different data types</span>
x = <span class="hljs-number">15</span>       <span class="hljs-comment"># Integer</span>
y = <span class="hljs-number">5.5</span>      <span class="hljs-comment"># Float</span>
name = <span class="hljs-string">"Alice"</span>  <span class="hljs-comment"># String</span>
is_student = <span class="hljs-literal">True</span>  <span class="hljs-comment"># Boolean</span>

<span class="hljs-comment"># Arithmetic Operations</span>
sum_result = x + y         <span class="hljs-comment"># Addition of integer and float</span>
difference = x - int(y)    <span class="hljs-comment"># Subtraction (converting float to integer)</span>
product = x * y            <span class="hljs-comment"># Multiplication</span>
division = x / y          <span class="hljs-comment"># Division (result will be a float)</span>
floor_division = x // y    <span class="hljs-comment"># Floor division (returns the integer part of the quotient)</span>
remainder = x % y         <span class="hljs-comment"># Modulus (returns the remainder of the division)</span>
power = x ** <span class="hljs-number">2</span>            <span class="hljs-comment"># Exponentiation (x raised to the power of 2)</span>

<span class="hljs-comment"># Comparison Operations</span>
is_equal = x == y          <span class="hljs-comment"># Check if x is equal to y (False)</span>
is_greater = x &gt; y         <span class="hljs-comment"># Check if x is greater than y (True)</span>
is_less_or_equal = x &lt;= y  <span class="hljs-comment"># Check if x is less than or equal to y (False)</span>

<span class="hljs-comment"># Logical Operations</span>
both_conditions = (x &gt; <span class="hljs-number">10</span>) <span class="hljs-keyword">and</span> (is_student)  
<span class="hljs-comment"># True if both conditions are met</span>
either_condition = (x &lt; <span class="hljs-number">5</span>) <span class="hljs-keyword">or</span> (y &gt; <span class="hljs-number">6</span>)       
<span class="hljs-comment"># True if at least one condition is met</span>
not_student = <span class="hljs-keyword">not</span> is_student                
<span class="hljs-comment"># True if is_student is False</span>

<span class="hljs-comment"># Assignment Operations</span>
x += <span class="hljs-number">3</span>  <span class="hljs-comment"># Equivalent to x = x + 3 (x is now 18)</span>
y -= <span class="hljs-number">2.5</span> <span class="hljs-comment"># Equivalent to y = y - 2.5 (y is now 3.0)</span>

<span class="hljs-comment"># Printing results with descriptive comments</span>
print(<span class="hljs-string">"Sum:"</span>, sum_result)                    
<span class="hljs-comment"># Output: Sum: 20.5</span>
print(<span class="hljs-string">"Difference:"</span>, difference)           
<span class="hljs-comment"># Output: Difference: 10</span>
print(<span class="hljs-string">"Product:"</span>, product)                 
<span class="hljs-comment"># Output: Product: 82.5</span>
print(<span class="hljs-string">"Division:"</span>, division)                 
<span class="hljs-comment"># Output: Division: 2.7272727272727275</span>
print(<span class="hljs-string">"Floor Division:"</span>, floor_division)      
<span class="hljs-comment"># Output: Floor Division: 2</span>
print(<span class="hljs-string">"Remainder:"</span>, remainder)             
<span class="hljs-comment"># Output: Remainder: 4.0</span>
print(<span class="hljs-string">"Power:"</span>, power)                     
<span class="hljs-comment"># Output: Power: 225</span>

print(<span class="hljs-string">"Is x equal to y?"</span>, is_equal)          
<span class="hljs-comment"># Output: Is x equal to y? False</span>
print(<span class="hljs-string">"Is x greater than y?"</span>, is_greater)      
<span class="hljs-comment"># Output: Is x greater than y? True</span>
print(<span class="hljs-string">"Is x less than or equal to y?"</span>, is_less_or_equal) 
<span class="hljs-comment"># Output: Is x less than or equal to y? False</span>

print(<span class="hljs-string">"Both conditions true?"</span>, both_conditions) 
<span class="hljs-comment"># Output: Both conditions true? True</span>
print(<span class="hljs-string">"Either condition true?"</span>, either_condition)  
<span class="hljs-comment"># Output: Either condition true? False</span>
print(<span class="hljs-string">"Not a student?"</span>, not_student)           
<span class="hljs-comment"># Output: Not a student? False</span>
print(<span class="hljs-string">"New value of x:"</span>, x)                    
<span class="hljs-comment"># Output: New value of x: 18</span>
print(<span class="hljs-string">"New value of y:"</span>, y)                    
<span class="hljs-comment"># Output: New value of y: 3.0</span>
</code></pre>
<h3 id="heading-14-control-flow">1.4 Control Flow</h3>
<p>In this section, we'll delve into the essential mechanisms for controlling the flow of your Python programs. This enables you to create dynamic and adaptable logic that responds to various conditions and data scenarios.</p>
<h4 id="heading-conditional-statements-making-decisions-in-your-code">Conditional Statements: Making Decisions in Your Code</h4>
<p>Conditional statements are the backbone of decision-making in programming. They allow you to execute specific blocks of code only if certain conditions are met. Python provides three main types of conditional statements:</p>
<p><strong>1. <code>if</code> Statement:</strong></p>
<ul>
<li>The most basic conditional statement.</li>
<li>Executes a block of code if a specified condition evaluates to <code>True</code>.</li>
</ul>
<pre><code class="lang-python">x = <span class="hljs-number">10</span>
<span class="hljs-keyword">if</span> x &gt; <span class="hljs-number">5</span>:
    <span class="hljs-comment">#This outputs "x is greater than 5" because 10 &gt; 5</span>
    print(<span class="hljs-string">"x is greater than 5"</span>)
</code></pre>
<p><strong>2. <code>if...else</code> Statement:</strong></p>
<ul>
<li>Provides an alternative block of code to execute if the <code>if</code> condition is <code>False</code>.</li>
</ul>
<pre><code class="lang-python"> x = <span class="hljs-number">3</span>
<span class="hljs-keyword">if</span> x &gt; <span class="hljs-number">5</span>:
    print(<span class="hljs-string">"x is greater than 5"</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"x is not greater than 5"</span>)
</code></pre>
<p><strong>3. <code>if...elif...else</code> Statement</strong></p>
<ul>
<li>Allows you to test multiple conditions in sequence.</li>
<li>The first condition that evaluates to True will trigger its corresponding code block.</li>
</ul>
<pre><code class="lang-python">score = <span class="hljs-number">85</span>
<span class="hljs-keyword">if</span> score &gt;= <span class="hljs-number">90</span>:
    print(<span class="hljs-string">"Grade: A"</span>)
<span class="hljs-keyword">elif</span> score &gt;= <span class="hljs-number">80</span>:
    print(<span class="hljs-string">"Grade: B"</span>)
<span class="hljs-keyword">elif</span> score &gt;= <span class="hljs-number">70</span>:
    print(<span class="hljs-string">"Grade: C"</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"Grade: F"</span>)
</code></pre>
<h4 id="heading-loops-repeating-actions-efficiently">Loops: Repeating Actions Efficiently</h4>
<p>Loops are used to repeatedly execute a block of code as long as a condition is met. Python offers two main types of loops:</p>
<p><strong>1. <code>for</code> Loop:</strong></p>
<p>The <code>for</code> loop is ideal for iterating over sequences (like lists, tuples, strings) or other iterable objects. It executes a block of code for each item in the sequence, providing a concise way to process collections of data.</p>
<p><strong>Iterating Over a Sequence:</strong></p>
<pre><code class="lang-python">fruits = [<span class="hljs-string">"apple"</span>, <span class="hljs-string">"banana"</span>, <span class="hljs-string">"orange"</span>]
<span class="hljs-keyword">for</span> fruit <span class="hljs-keyword">in</span> fruits:
    print(fruit)  <span class="hljs-comment"># Output: apple, banana, orange</span>
</code></pre>
<p><strong>Using the <code>range()</code> Function:</strong></p>
<p>The <code>range()</code> function generates a sequence of numbers, making it perfect for situations where you need to repeat an action a specific number of times.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">5</span>):  <span class="hljs-comment"># Range of 0 to 4 (inclusive)</span>
    print(i)        <span class="hljs-comment"># Output: 0, 1, 2, 3, 4</span>
</code></pre>
<p>You can customize the <code>range()</code> function to start and end at specific values or increment by a different step.</p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">2</span>, <span class="hljs-number">10</span>, <span class="hljs-number">2</span>):  <span class="hljs-comment"># Start at 2, end before 10, increment by 2</span>
    print(i)                <span class="hljs-comment"># Output: 2, 4, 6, 8</span>
</code></pre>
<p><strong>2. <code>while</code> Loop:</strong></p>
<ul>
<li>Continues to execute a block of code as long as a condition remains <code>True</code>.</li>
</ul>
<pre><code class="lang-python">count = <span class="hljs-number">0</span>
<span class="hljs-keyword">while</span> count &lt; <span class="hljs-number">5</span>:
    print(count)
    count += <span class="hljs-number">1</span>  <span class="hljs-comment"># Output: 0, 1, 2, 3, 4</span>
</code></pre>
<h4 id="heading-break-and-continue-statements-controlling-loop-execution"><code>break</code> and <code>continue</code> Statements: Controlling Loop Execution</h4>
<ul>
<li><strong><code>break</code>:</strong> Immediately terminates the loop's execution, even if the loop condition is still <code>True</code>.</li>
<li><strong><code>continue</code>:</strong> Skips the rest of the current iteration and moves to the next iteration.</li>
</ul>
<p><strong>Example in Python:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]:
    <span class="hljs-keyword">if</span> num == <span class="hljs-number">3</span>:
        <span class="hljs-keyword">break</span>          <span class="hljs-comment"># Exit the loop when num is 3</span>
    print(num)         <span class="hljs-comment"># Output: 1, 2</span>

<span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]:
    <span class="hljs-keyword">if</span> num % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>:
        <span class="hljs-keyword">continue</span>     <span class="hljs-comment"># Skip even numbers</span>
    print(num)         <span class="hljs-comment"># Output: 1, 3, 5</span>
</code></pre>
<p><strong>Key Takeaways</strong></p>
<ul>
<li>Conditional statements enable your code to make decisions based on varying conditions.</li>
<li>Loops automate repetitive tasks, improving code efficiency.</li>
<li>Use <code>break</code> and <code>continue</code> to precisely control the flow of your loops.</li>
</ul>
<p>By mastering control flow, you gain the ability to create versatile and adaptable programs that can handle diverse data scenarios. This knowledge will be invaluable as you tackle increasingly complex data analysis tasks in the upcoming chapters.</p>
<h5 id="heading-code-example">Code Example</h5>
<p>This code demonstrates how Python's control flow tools – loops (<code>for</code>, <code>while</code>) and conditional statements (<code>if...else</code>) – can be used to analyze structured customer data.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Scenario: Analyzing Customer Data</span>

<span class="hljs-comment"># Sample customer data (list of dictionaries)</span>
customers = [
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Alice"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">35</span>, <span class="hljs-string">"is_member"</span>: <span class="hljs-literal">True</span>, <span class="hljs-string">"purchases"</span>: [<span class="hljs-number">50</span>, <span class="hljs-number">80</span>, <span class="hljs-number">120</span>]},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Bob"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">28</span>, <span class="hljs-string">"is_member"</span>: <span class="hljs-literal">False</span>, <span class="hljs-string">"purchases"</span>: [<span class="hljs-number">25</span>, <span class="hljs-number">40</span>]},
    {<span class="hljs-string">"name"</span>: <span class="hljs-string">"Charlie"</span>, <span class="hljs-string">"age"</span>: <span class="hljs-number">42</span>, <span class="hljs-string">"is_member"</span>: <span class="hljs-literal">True</span>, <span class="hljs-string">"purchases"</span>: [<span class="hljs-number">15</span>, <span class="hljs-number">65</span>, <span class="hljs-number">90</span>, <span class="hljs-number">110</span>]},
]

total_spent = <span class="hljs-number">0</span>  <span class="hljs-comment"># Initialize variable to track total spending</span>
member_count = <span class="hljs-number">0</span>  <span class="hljs-comment"># Initialize variable to count members</span>

<span class="hljs-comment"># Iterate through customers using a for loop</span>
<span class="hljs-keyword">for</span> customer <span class="hljs-keyword">in</span> customers:
    name = customer[<span class="hljs-string">"name"</span>]
    age = customer[<span class="hljs-string">"age"</span>]
    is_member = customer[<span class="hljs-string">"is_member"</span>]
    purchases = customer[<span class="hljs-string">"purchases"</span>]

    <span class="hljs-comment"># Conditional statement to check membership status</span>
    <span class="hljs-keyword">if</span> is_member:
        print(<span class="hljs-string">f"<span class="hljs-subst">{name}</span> is a member and has spent:"</span>)
        member_count += <span class="hljs-number">1</span> 
    <span class="hljs-keyword">else</span>:
        print(<span class="hljs-string">f"<span class="hljs-subst">{name}</span> is not a member and has spent:"</span>)

    <span class="hljs-comment"># Calculate total spent for each customer using a while loop</span>
    purchase_index = <span class="hljs-number">0</span>
    <span class="hljs-keyword">while</span> purchase_index &lt; len(purchases):
        purchase = purchases[purchase_index]
        total_spent += purchase
        print(<span class="hljs-string">f"  - $<span class="hljs-subst">{purchase}</span>"</span>)  <span class="hljs-comment"># Print individual purchase amounts</span>
        purchase_index += <span class="hljs-number">1</span>        <span class="hljs-comment"># Increment the index</span>

    <span class="hljs-comment"># Continue statement to skip rest of the loop for non-members</span>
    <span class="hljs-keyword">if</span> <span class="hljs-keyword">not</span> is_member:
        <span class="hljs-keyword">continue</span>  <span class="hljs-comment"># Skip calculating average for non-members</span>

    <span class="hljs-comment"># Calculate average spending for members</span>
    average_spent = total_spent / len(purchases)
    print(<span class="hljs-string">f"  Average spending: $<span class="hljs-subst">{average_spent:<span class="hljs-number">.2</span>f}</span>\n"</span>)

<span class="hljs-comment"># Calculate overall average spending</span>
<span class="hljs-keyword">if</span> member_count &gt; <span class="hljs-number">0</span>:  <span class="hljs-comment"># Avoid division by zero</span>
    overall_average = total_spent / member_count  <span class="hljs-comment"># Calculate only for members</span>
    print(<span class="hljs-string">f"Overall average spending for members: $<span class="hljs-subst">{overall_average:<span class="hljs-number">.2</span>f}</span>"</span>)
</code></pre>
<p>This outputs: </p>
<pre><code class="lang-python">Alice <span class="hljs-keyword">is</span> a member <span class="hljs-keyword">and</span> has spent:
  - $<span class="hljs-number">50</span>
  - $<span class="hljs-number">80</span>
  - $<span class="hljs-number">120</span>
  Average spending: $<span class="hljs-number">83.33</span>

Bob <span class="hljs-keyword">is</span> <span class="hljs-keyword">not</span> a member <span class="hljs-keyword">and</span> has spent:
  - $<span class="hljs-number">25</span>
  - $<span class="hljs-number">40</span>
Charlie <span class="hljs-keyword">is</span> a member <span class="hljs-keyword">and</span> has spent:
  - $<span class="hljs-number">15</span>
  - $<span class="hljs-number">65</span>
  - $<span class="hljs-number">90</span>
  - $<span class="hljs-number">110</span>
  Average spending: $<span class="hljs-number">148.75</span>

Overall average spending <span class="hljs-keyword">for</span> members: $<span class="hljs-number">297.50</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>The code starts with sample customer data. It calculates the total amount spent and the average spending for members and outputs these values.</li>
<li>A <code>for</code> loop is used to iterate over each customer in the <code>customers</code> list.</li>
<li>An <code>if...else</code> statement is used to check if a customer is a member, printing different messages accordingly.</li>
<li>A <code>while</code> loop is used to iterate over the purchases of each customer and calculate the total spent.</li>
<li>A <code>continue</code> statement is used to skip the calculation of average spending for non-members.</li>
</ul>
<p><strong>Key Takeaways:</strong></p>
<p>This example demonstrates how to use nested loops and conditional statements to perform calculations on data stored in a list of dictionaries.</p>
<ul>
<li>The <code>for</code> loop iterates through the list of customers and extracts information about each customer.</li>
<li>The <code>while</code> loop is used to calculate the total spent for each customer by iterating through their list of purchases.</li>
<li>The <code>if-else</code> statement is used to differentiate between members and non-members. The <code>continue</code> statement is used to skip the average spending calculation for non-members. </li>
</ul>
<p>Finally, the code calculates and prints the overall average spending for members if there are any members in the customer list.</p>
<h3 id="heading-15-functions-in-python">1.5 Functions in Python</h3>
<p>Python functions are fundamental tools for code organization, reusability, and readability. They act like self-contained mini-programs, each designed to perform a specific task within your larger program.  </p>
<p>By encapsulating code into functions, you can avoid repeating the same code blocks throughout your project. This makes your code cleaner, more modular, and easier to maintain.</p>
<p>Imagine a function as a specialized tool in your toolbox. Instead of writing out the instructions for a task every time you need it, you create a function once and then "call" it whenever you need to perform that task. This not only saves you time but also makes your code more organized and easier to understand.</p>
<p>In this section, we'll explore the anatomy of Python functions, including how to define them, call them, and pass data to them. We'll cover different types of arguments, return values, and the concept of lambda functions, which are concise expressions for creating simple functions on the fly.</p>
<p>By the end of this part, you'll have a solid understanding of how functions work in Python, empowering you to write more structured and efficient code that is both reusable and easier to maintain. You'll also be well-prepared to tackle more advanced Python concepts like recursion, decorators, and generators, which leverage the power of functions to provide even greater flexibility and expressiveness in your code.</p>
<p>Now, let's explore the fundamental concepts behind Python functions, the building blocks that enable you to create reusable and well-structured code.</p>
<h4 id="heading-anatomy-of-a-python-function">Anatomy of a Python Function</h4>
<p>A Python function is a self-contained unit of code designed to perform a specific task. Let's dissect its structure. Here's an example of a Python function:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name</span>):</span>
    <span class="hljs-string">"""This function prints a personalized greeting."""</span>
    print(<span class="hljs-string">f"Hello, <span class="hljs-subst">{name}</span>!"</span>)
</code></pre>
<ol>
<li><strong><code>def</code> Keyword:</strong> This keyword signals the start of a function definition, indicating that you're about to create a new function.</li>
<li><strong>Function Name:</strong> Choose a descriptive name that clearly reflects the function's purpose. Adhering to Python's PEP 8 style guide, use lowercase letters and separate words with underscores (for example, <code>calculate_average</code>, <code>process_data</code>).</li>
<li><strong>Parameters (Optional):</strong> Parameters act as placeholders for the values (arguments) you pass into the function when you call it. They are listed within parentheses after the function name, separated by commas if there are multiple parameters.</li>
<li><strong>Docstring (Optional but Highly Recommended):</strong> A docstring is a string literal enclosed in triple quotes (<code>"""</code>) that immediately follows the function header. It provides a concise description of the function's purpose, its parameters, and what it returns (if anything). Docstrings are essential for documenting your code and making it easier for you and others to understand how your functions work.</li>
<li><strong>Function Body:</strong> The indented block of code beneath the function header constitutes the function body. This is where you write the actual instructions that define the function's behavior.</li>
<li><strong>Return Statement (Optional):</strong> The <code>return</code> statement is used to send a value back to the code that called the function. If a function doesn't have an explicit <code>return</code> statement, it implicitly returns <code>None</code>.</li>
</ol>
<p>In this example, <code>greet</code> is the function name, <code>name</code> is a parameter, and the docstring explains the function's purpose.</p>
<h4 id="heading-calling-functions">Calling Functions</h4>
<p>To execute the code within a function, you call it by its name, followed by parentheses. If the function expects arguments, you provide them within the parentheses.</p>
<pre><code class="lang-python">greet(<span class="hljs-string">"Alice"</span>)  <span class="hljs-comment"># Calls the greet function and passes "Alice" as an argument</span>
</code></pre>
<p><strong>Calling Functions Without Arguments:</strong> If a function doesn't require any input, you still need to include the parentheses when calling it.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">say_hello</span>():</span>
    <span class="hljs-string">"""This function prints a generic greeting."""</span>
    print(<span class="hljs-string">"Hello there!"</span>)

say_hello()  <span class="hljs-comment"># Output: Hello there!</span>
</code></pre>
<h4 id="heading-function-arguments-and-parameters">Function Arguments and Parameters</h4>
<p>When defining and calling functions in Python, you'll encounter different ways of supplying information to them—these are known as function arguments. Let's delve into the various types of arguments and how they shape your functions' behavior:</p>
<p><strong>1. Positional Arguments:</strong> Positional arguments are the most common way to pass values to a function. Their meaning is determined by their position in the function call, matching the order of parameters defined in the function header.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">describe_pet</span>(<span class="hljs-params">animal, name</span>):</span>
    print(<span class="hljs-string">f"I have a <span class="hljs-subst">{animal}</span> named <span class="hljs-subst">{name}</span>."</span>)

describe_pet(<span class="hljs-string">"dog"</span>, <span class="hljs-string">"Fido"</span>)  <span class="hljs-comment"># Output: I have a dog named Fido.</span>
</code></pre>
<p><strong>2. Keyword Arguments:</strong> Keyword arguments offer more flexibility by allowing you to explicitly specify the parameter name when passing the argument. This makes your code more self-documenting and allows you to change the order of arguments in the function call.</p>
<pre><code class="lang-python">describe_pet(name=<span class="hljs-string">"Whiskers"</span>, animal=<span class="hljs-string">"cat"</span>)  <span class="hljs-comment"># Output: I have a cat named Whiskers.</span>
</code></pre>
<p><strong>3. Default Arguments:</strong> Default arguments are values that are automatically assigned to parameters if no argument is provided in the function call. They provide convenience and allow you to create functions with optional parameters.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name=<span class="hljs-string">"there"</span></span>):</span>  <span class="hljs-comment"># 'there' is the default value for name</span>
    print(<span class="hljs-string">f"Hello, <span class="hljs-subst">{name}</span>!"</span>)

greet()          <span class="hljs-comment"># Output: Hello, there!</span>
greet(<span class="hljs-string">"Alice"</span>)  <span class="hljs-comment"># Output: Hello, Alice!</span>
</code></pre>
<p><strong>4. Variable-Length Arguments:</strong> Python offers two special syntaxes for handling a varying number of arguments:</p>
<ul>
<li><code>*args</code>:  Collects any additional positional arguments passed to the function into a tuple.</li>
<li><code>**kwargs</code>:  Collects any additional keyword arguments passed to the function into a dictionary.</li>
</ul>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_total</span>(<span class="hljs-params">*args</span>):</span>
    <span class="hljs-keyword">return</span> sum(args)

print(calculate_total(<span class="hljs-number">5</span>, <span class="hljs-number">10</span>, <span class="hljs-number">15</span>))  <span class="hljs-comment"># Output: 30</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">print_info</span>(<span class="hljs-params">**kwargs</span>):</span>
    <span class="hljs-keyword">for</span> key, value <span class="hljs-keyword">in</span> kwargs.items():
        print(<span class="hljs-string">f"<span class="hljs-subst">{key}</span>: <span class="hljs-subst">{value}</span>"</span>)

print_info(name=<span class="hljs-string">"Bob"</span>, age=<span class="hljs-number">30</span>, city=<span class="hljs-string">"New York"</span>)
</code></pre>
<h4 id="heading-passing-immutable-vs-mutable-arguments-the-impact-of-change">Passing Immutable vs. Mutable Arguments: The Impact of Change</h4>
<p>In Python, data types can be classified as either immutable (unchangeable) or mutable (changeable). This distinction plays a crucial role when passing arguments to functions.</p>
<p><strong>Immutable Arguments:</strong> When you pass immutable objects (like numbers, strings, or tuples) to a function, any changes made to the object within the function <strong>do not</strong> affect the original object.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">modify_string</span>(<span class="hljs-params">text</span>):</span>
    text += <span class="hljs-string">" world!"</span>  <span class="hljs-comment"># Modifies a copy of the string</span>
    print(<span class="hljs-string">"Inside function:"</span>, text)

message = <span class="hljs-string">"Hello"</span>
modify_string(message)  
print(<span class="hljs-string">"Outside function:"</span>, message)  <span class="hljs-comment"># Original string remains unchanged</span>
</code></pre>
<p><strong>Output:</strong></p>
<p>Inside function: Hello world! Outside function: Hello</p>
<p><strong>Mutable Arguments:</strong> When you pass mutable objects (like lists or dictionaries) to a function, changes made within the function <strong>can</strong> affect the original object.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">append_item</span>(<span class="hljs-params">my_list, item</span>):</span>
    my_list.append(item)  <span class="hljs-comment"># Modifies the original list</span>
    print(<span class="hljs-string">"Inside function:"</span>, my_list)

data = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>]
append_item(data, <span class="hljs-number">4</span>)
print(<span class="hljs-string">"Outside function:"</span>, data)  <span class="hljs-comment"># Original list is modified</span>
</code></pre>
<p><strong>Output:</strong></p>
<p>Inside function: [1, 2, 3, 4] Outside function: [1, 2, 3, 4]</p>
<p>Understanding how arguments are passed—by assignment for immutables and by reference for mutables—is crucial for avoiding unexpected side effects in your code. Consider making copies of mutable objects if you need to modify them within a function without affecting the original data.</p>
<p>By grasping these concepts, you'll be well-equipped to harness the full power of function arguments and create flexible, reusable code for your data analysis projects.</p>
<h4 id="heading-return-values">Return Values</h4>
<p>The <code>return</code> statement is your function's way of giving something back to the code that called it. Think of it as a function's output or the result of its work.</p>
<p>Understanding how to use return values effectively is key to utilizing functions to their full potential.</p>
<h5 id="heading-the-return-statement-syntax-and-usage">The <code>return</code> Statement: Syntax and Usage</h5>
<p>The <code>return</code> statement consists of the keyword <code>return</code> followed by the value you want the function to return. The value can be of any data type in Python, including numbers, strings, lists, dictionaries, or even other functions.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">add_numbers</span>(<span class="hljs-params">a, b</span>):</span>
    <span class="hljs-string">"""Adds two numbers and returns the result."""</span>
    result = a + b
    <span class="hljs-keyword">return</span> result  <span class="hljs-comment"># Explicitly returns the calculated result</span>

sum_value = add_numbers(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>)  <span class="hljs-comment"># sum_value now holds the returned value 8</span>
</code></pre>
<p><strong>Returning Multiple Values:</strong> Python allows you to return multiple values from a function by simply separating them with commas in the <code>return</code> statement. The returned values are packed into a tuple, which you can then unpack on the calling side.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">get_name_and_age</span>():</span>
    name = <span class="hljs-string">"Alice"</span>
    age = <span class="hljs-number">30</span>
    <span class="hljs-keyword">return</span> name, age

person_name, person_age = get_name_and_age() 
print(person_name, person_age) <span class="hljs-comment"># Output: Alice 30</span>
</code></pre>
<p><strong>Implicit Return of None:</strong> If a function doesn't include a <code>return</code> statement, or if the <code>return</code> statement is encountered without a value, the function implicitly returns <code>None</code>. This is the Python equivalent of "nothing."</p>
<p>Python example:</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name</span>):</span>
    print(<span class="hljs-string">f"Hello, <span class="hljs-subst">{name}</span>!"</span>)  <span class="hljs-comment"># No return statement</span>

result = greet(<span class="hljs-string">"Bob"</span>)
print(result)  <span class="hljs-comment"># Output: None (since greet doesn't return anything)</span>
</code></pre>
<h5 id="heading-using-return-values-the-power-of-functions">Using Return Values: The Power of Functions</h5>
<p>Return values are a powerful way to integrate functions into your data analysis workflow. Here's how you can use them:</p>
<p><strong>Store in Variables:</strong> Assign the returned value to a variable for later use.</p>
<p>Here's an example in Python:</p>
<pre><code class="lang-python">average_score = calculate_average([<span class="hljs-number">85</span>, <span class="hljs-number">92</span>, <span class="hljs-number">78</span>])
</code></pre>
<p><strong>Chain Functions:</strong> Pass the return value of one function as an argument to another.</p>
<p>Here's a Python example:</p>
<pre><code class="lang-python">filtered_data = filter_data(load_data(<span class="hljs-string">"sales.csv"</span>))
</code></pre>
<p><strong>Conditional Logic:</strong> Use return values in conditional statements to make decisions.</p>
<p>Here's a Python example:</p>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> is_valid(user_input):
    process_data(user_input)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"Invalid input."</span>)
</code></pre>
<p><strong>Data Transformation:</strong> Apply functions to transform or aggregate data.</p>
<p>And here's a Python example:</p>
<pre><code class="lang-python">sales_summary = summarize_sales(sales_data)
</code></pre>
<p><strong>Key Takeaways:</strong></p>
<ul>
<li>The <code>return</code> statement is the mechanism for getting results back from a function.</li>
<li>You can return values of any data type, including multiple values.</li>
<li>Functions without a <code>return</code> statement implicitly return <code>None</code>.</li>
<li>Return values enable you to chain functions, use conditional logic, and perform data transformations, making functions a fundamental building block for complex data analysis tasks.</li>
</ul>
<h4 id="heading-lambda-functions">Lambda Functions</h4>
<p>In this section, we'll delve into the world of lambda functions, a unique feature of Python that allows you to define concise, anonymous functions inline. These functions offer a streamlined way to express simple operations and are particularly useful in scenarios where you need a function for a short period or as an argument to other functions.</p>
<h5 id="heading-understanding-lambda-functions">Understanding Lambda Functions:</h5>
<p>Lambda functions are aptly named because they are defined using the <code>lambda</code> keyword. They are also known as anonymous functions because they don't have a traditional name like functions defined using the <code>def</code> keyword.</p>
<p>The syntax of a lambda function is as follows:</p>
<pre><code class="lang-python"><span class="hljs-keyword">lambda</span> arguments: expression
</code></pre>
<p>Let's break it down:</p>
<ul>
<li><strong>lambda:</strong> The keyword indicating that you're creating a lambda function.</li>
<li><strong>arguments:</strong> A comma-separated list of zero or more arguments.</li>
<li><strong>expression:</strong> A single expression that the lambda function evaluates and returns.</li>
</ul>
<p>For example, the lambda function <code>lambda x: x * 2</code> takes an argument <code>x</code> and returns the result of multiplying it by 2.</p>
<h5 id="heading-use-cases-for-lambda-functions">Use Cases for Lambda Functions</h5>
<p>Lambda functions are often employed in conjunction with higher-order functions, which are functions that take other functions as arguments or return functions as results. </p>
<p>Let's explore some common scenarios where lambda functions shine:</p>
<p><strong>1. Sorting:</strong></p>
<pre><code class="lang-python">points = [(<span class="hljs-number">3</span>, <span class="hljs-number">2</span>), (<span class="hljs-number">1</span>, <span class="hljs-number">4</span>), (<span class="hljs-number">2</span>, <span class="hljs-number">1</span>)]
sorted_points = sorted(points, key=<span class="hljs-keyword">lambda</span> x: x[<span class="hljs-number">1</span>])  
print(sorted_points)  <span class="hljs-comment"># Output: [(2, 1), (3, 2), (1, 4)]</span>
</code></pre>
<p><strong>Explanation:</strong> In this example, the lambda function sorts a list of points based on their y-coordinates. The lambda function <code>lambda x: x[1]</code> takes each point (<code>x</code>) as input and returns the y-coordinate (<code>x[1]</code>). This lambda function is passed to the <code>sorted()</code> function as the <code>key</code> to customize the sorting process.</p>
<p><strong>2. Filtering:</strong></p>
<pre><code class="lang-python">numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]
even_numbers = list(filter(<span class="hljs-keyword">lambda</span> x: x % <span class="hljs-number">2</span> == <span class="hljs-number">0</span>, numbers))
print(even_numbers)  <span class="hljs-comment"># Output: [2, 4, 6]</span>
</code></pre>
<p><strong>Explanation:</strong> Here, we use the <code>filter()</code> function to extract even numbers from a list. The lambda function <code>lambda x: x % 2 == 0</code> tests if a number is even. The <code>filter()</code> function applies this lambda function to each item in the list <code>numbers</code> and includes only those for which the lambda function returns <code>True</code>.</p>
<p><strong>3. Mapping (Applying a Function to Each Item):</strong></p>
<pre><code class="lang-python">numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
squares = list(map(<span class="hljs-keyword">lambda</span> x: x**<span class="hljs-number">2</span>, numbers))
print(squares)  <span class="hljs-comment"># Output: [1, 4, 9, 16, 25]</span>
</code></pre>
<p><strong>Explanation:</strong> In this case, the lambda function <code>lambda x: x**2</code> squares each element of the list, and the <code>map</code> function is used to apply this lambda function to all the elements in the list.</p>
<p><strong>Key Takeaways:</strong></p>
<ul>
<li>Lambda functions are concise and efficient for expressing simple operations.</li>
<li>They are often used with higher-order functions like <code>sorted()</code>, <code>filter()</code>, and <code>map()</code>.</li>
<li>Lambda functions can enhance code readability by providing inline function definitions.</li>
</ul>
<p>By understanding lambda functions and their use cases, you can streamline your Python code and tackle various tasks with greater efficiency and elegance. </p>
<p>As you progress in your data analysis journey, you'll find that lambda functions are a versatile tool for expressing concise logic and enhancing the readability of your code.</p>
<h4 id="heading-function-scope">Function Scope</h4>
<p>Understanding how Python manages variable accessibility is crucial for writing robust and error-free code. The concept of scope defines where a variable can be accessed and modified within your program. </p>
<p>Let's delve into the two primary types of scope in Python: local and global.</p>
<h5 id="heading-local-scope-variables-within-functions">Local Scope: Variables Within Functions</h5>
<p>Variables defined <strong>within</strong> a function are considered to have <em>local scope</em>. This means they are only accessible and usable within the function where they are defined. Once the function finishes executing, these local variables are destroyed and their values are lost.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_discount</span>(<span class="hljs-params">price, discount_percentage</span>):</span>
    discount_amount = price * (discount_percentage / <span class="hljs-number">100</span>)
    final_price = price - discount_amount
    <span class="hljs-keyword">return</span> final_price

print(calculate_discount(<span class="hljs-number">100</span>, <span class="hljs-number">15</span>))  <span class="hljs-comment"># Output: 85.0</span>

<span class="hljs-comment"># Trying to access 'discount_amount' outside the function would result in a NameError</span>
<span class="hljs-comment"># print(discount_amount)  # This would raise an error</span>
</code></pre>
<p>In this example, <code>discount_amount</code> and <code>final_price</code> are local variables, meaning they exist only within the <code>calculate_discount</code> function. Trying to access them outside the function will result in an error.</p>
<h5 id="heading-global-scope-variables-outside-functions">Global Scope: Variables Outside Functions</h5>
<p>Variables defined <strong>outside</strong> any function are said to have <em>global scope</em>. This means they can be accessed and modified from anywhere within your code, both inside and outside functions.</p>
<pre><code class="lang-python">pi = <span class="hljs-number">3.14159</span>  <span class="hljs-comment"># Global variable</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_area</span>(<span class="hljs-params">radius</span>):</span>
    area = pi * radius**<span class="hljs-number">2</span>
    <span class="hljs-keyword">return</span> area

print(calculate_area(<span class="hljs-number">5</span>))  <span class="hljs-comment"># Output: 78.53975</span>
</code></pre>
<p>Here, <code>pi</code> is a global variable that can be used inside the <code>calculate_area</code> function.</p>
<h5 id="heading-the-global-keyword-modifying-globals-within-functions-use-with-caution">The <code>global</code> Keyword: Modifying Globals Within Functions (Use with Caution)</h5>
<p>While you can access global variables inside functions, modifying them directly is generally discouraged. If you need to change a global variable within a function, you should explicitly declare it using the <code>global</code> keyword.</p>
<pre><code class="lang-python">counter = <span class="hljs-number">0</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">increment_counter</span>():</span>
    <span class="hljs-keyword">global</span> counter
    counter += <span class="hljs-number">1</span>

increment_counter()
print(counter)  <span class="hljs-comment"># Output: 1</span>
</code></pre>
<p><strong>Caution:</strong> Overusing global variables can lead to code that is difficult to understand, debug, and maintain. It's generally better to pass variables as arguments to functions and return results whenever possible.</p>
<p><strong>Key Takeaways</strong></p>
<ul>
<li>Local variables exist only within the functions where they are defined.</li>
<li>Global variables can be accessed from anywhere in your code.</li>
<li>Use the <code>global</code> keyword with caution when modifying global variables within functions.</li>
</ul>
<p>By understanding the concepts of local and global scope, you can write more robust and predictable Python code, ensuring that variables are accessible only where they are intended to be used.</p>
<h4 id="heading-recursion">Recursion</h4>
<p>Recursion, a function's ability to invoke itself, is a powerful technique that can simplify complex problems. </p>
<p>Imagine a set of Russian nesting dolls, each containing a smaller version of itself. Recursion follows a similar pattern, breaking a problem into smaller, identical subproblems until a base case is reached.</p>
<p>Consider the classic example of calculating the factorial of a number:</p>
<p><strong>Recursive Factorial:</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">factorial_recursive</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-string">"""Calculates the factorial of a number using recursion."""</span>
    <span class="hljs-keyword">if</span> n == <span class="hljs-number">0</span>:
        <span class="hljs-keyword">return</span> <span class="hljs-number">1</span>  <span class="hljs-comment"># Base case: 0! = 1</span>
    <span class="hljs-keyword">else</span>:
        <span class="hljs-keyword">return</span> n * factorial_recursive(n - <span class="hljs-number">1</span>)  <span class="hljs-comment"># Recursive step</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ol>
<li><strong>Base Case:</strong> The function first checks if the input <code>n</code> is 0. If so, it returns 1, as the factorial of 0 is defined as 1. This is the stopping point of the recursion.</li>
<li><strong>Recursive Step:</strong> If <code>n</code> is not 0, the function calls itself with the argument <code>n - 1</code>. This recursive call calculates the factorial of the next smaller number.</li>
<li><strong>Unwinding:</strong> The recursive calls continue until the base case (<code>n = 0</code>) is reached. At that point, the function returns 1. The return values then "bubble up" through the call stack, multiplying the results at each level until the original function call returns the final factorial.</li>
</ol>
<p><strong>Iterative Factorial:</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">factorial_iterative</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-string">"""Calculates the factorial of a number using iteration (loop)."""</span>
    result = <span class="hljs-number">1</span>
    <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(<span class="hljs-number">1</span>, n + <span class="hljs-number">1</span>):
        result *= i  <span class="hljs-comment"># Multiply the result by each number from 1 to n</span>
    <span class="hljs-keyword">return</span> result
</code></pre>
<p><strong>Explanation:</strong></p>
<ol>
<li><strong>Initialization:</strong> The function initializes a variable <code>result</code> to 1. This will store the accumulating factorial.</li>
<li><strong>Iteration:</strong>  A <code>for</code> loop iterates through numbers from 1 up to <code>n</code>. In each iteration, the current number (<code>i</code>) is multiplied with the <code>result</code> and stored back in <code>result</code>.</li>
<li><strong>Return Result:</strong> After the loop completes, the function returns the final value of <code>result</code>, which is the calculated factorial.</li>
</ol>
<p><strong>Comparison:</strong></p>
<table><tbody><tr><th>Feature</th><th>Recursive</th><th>Iterative</th></tr><tr><td>Approach</td><td>Breaks the problem into smaller, identical subproblems</td><td>Solves the problem step-by-step using a loop</td></tr><tr><td>Code Style</td><td>More concise and elegant for problems with recursive structures</td><td>Might be easier to understand for simpler problems</td></tr><tr><td>Performance</td><td>Can be less efficient due to function call overhead</td><td>Generally more efficient for simpler calculations</td></tr><tr><td>Stack Usage</td><td>Higher stack usage for deeper recursion</td><td>Lower stack usage</td></tr></tbody></table>

<h4 id="heading-how-to-choose-the-right-approach">How to Choose the Right Approach:</h4>
<p><strong>Recursive:</strong> Consider recursion when the problem's structure naturally lends itself to being divided into smaller, self-similar subproblems.</p>
<pre><code class="lang-python">
<span class="hljs-keyword">import</span> os

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">list_files_recursive</span>(<span class="hljs-params">path</span>):</span>
    <span class="hljs-string">"""Recursively lists all files in a directory."""</span>
    <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> os.listdir(path):
        item_path = os.path.join(path, item)
        <span class="hljs-keyword">if</span> os.path.isfile(item_path):  <span class="hljs-comment"># Base case: it's a file</span>
            print(item_path)
        <span class="hljs-keyword">elif</span> os.path.isdir(item_path):  <span class="hljs-comment"># Recursive case: it's a directory</span>
            list_files_recursive(item_path)

list_files_recursive(<span class="hljs-string">"/my_documents"</span>)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>The function <code>list_files_recursive</code> takes a directory path as input.</li>
<li>It checks each item in the directory. If it's a file, it prints the path.</li>
<li>If the item is a subdirectory, the function recursively calls itself with the subdirectory's path.</li>
<li>This continues until all files within the directory tree are found.</li>
</ul>
<p><strong>Iterative:</strong> Prefer iteration when the problem can be solved step-by-step, especially if performance is a primary concern.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_average</span>(<span class="hljs-params">numbers</span>):</span>
    <span class="hljs-string">"""Calculates the average of a list of numbers iteratively."""</span>
    total = <span class="hljs-number">0</span>
    count = <span class="hljs-number">0</span>
    <span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> numbers:
        total += num
        count += <span class="hljs-number">1</span>
    <span class="hljs-keyword">return</span> total / count

numbers = [<span class="hljs-number">85</span>, <span class="hljs-number">92</span>, <span class="hljs-number">78</span>, <span class="hljs-number">95</span>, <span class="hljs-number">88</span>]
average = calculate_average(numbers)
print(average)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>The function <code>calculate_average</code> takes a list of numbers as input.</li>
<li>It uses a <code>for</code> loop to iterate through the numbers.</li>
<li>Inside the loop, it accumulates the <code>total</code> and counts the number of elements (<code>count</code>).</li>
<li>Finally, it returns the average calculated by dividing the <code>total</code> by <code>count</code>.</li>
</ul>
<p><strong>Hybrid:</strong> Sometimes, a combination of recursion and iteration can be the most effective solution.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">merge_sort</span>(<span class="hljs-params">arr</span>):</span>
    <span class="hljs-string">"""Sorts an array using the merge sort algorithm (hybrid)."""</span>
    <span class="hljs-keyword">if</span> len(arr) &gt; <span class="hljs-number">1</span>:
        mid = len(arr) // <span class="hljs-number">2</span>  
        left_half = arr[:mid]
        right_half = arr[mid:]

        merge_sort(left_half)  <span class="hljs-comment"># Recursive calls to sort halves</span>
        merge_sort(right_half)

        i = j = k = <span class="hljs-number">0</span>
        <span class="hljs-keyword">while</span> i &lt; len(left_half) <span class="hljs-keyword">and</span> j &lt; len(right_half):  <span class="hljs-comment"># Iterative merging</span>
            <span class="hljs-keyword">if</span> left_half[i] &lt; right_half[j]:
                arr[k] = left_half[i]
                i += <span class="hljs-number">1</span>
            <span class="hljs-keyword">else</span>:
                arr[k] = right_half[j]
                j += <span class="hljs-number">1</span>
            k += <span class="hljs-number">1</span>

        <span class="hljs-keyword">while</span> i &lt; len(left_half):  <span class="hljs-comment"># Copy remaining elements of left_half</span>
            arr[k] = left_half[i]
            i += <span class="hljs-number">1</span>
            k += <span class="hljs-number">1</span>
        <span class="hljs-keyword">while</span> j &lt; len(right_half):  <span class="hljs-comment"># Copy remaining elements of right_half</span>
            arr[k] = right_half[j]
            j += <span class="hljs-number">1</span>
            k += <span class="hljs-number">1</span>

numbers = [<span class="hljs-number">38</span>, <span class="hljs-number">27</span>, <span class="hljs-number">43</span>, <span class="hljs-number">3</span>, <span class="hljs-number">9</span>, <span class="hljs-number">82</span>, <span class="hljs-number">10</span>]
merge_sort(numbers)
print(numbers)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>The <code>merge_sort</code> function takes an unsorted list <code>arr</code> as input.</li>
<li>It recursively divides the list into halves until each half contains a single element (base case).</li>
<li>Then, it iteratively merges the sorted halves back together in the correct order.</li>
</ul>
<h5 id="heading-the-risks-of-recursion">The Risks of Recursion</h5>
<p>While recursion can be elegant, it's crucial to use it judiciously.</p>
<ul>
<li><strong>Infinite Recursion:</strong> Without a proper base case, a recursive function can call itself indefinitely, leading to a stack overflow error. This is akin to the nesting dolls never ending.</li>
<li><strong>Performance:</strong> Recursion can be computationally expensive, as each function call adds overhead. In some cases, iterative solutions (using loops) might be more efficient.</li>
</ul>
<h5 id="heading-when-to-choose-recursion">When to Choose Recursion:</h5>
<p>Recursion excels when a problem naturally decomposes into smaller, self-similar subproblems.  </p>
<p>For instance, traversing tree-like structures, exploring complex data structures, or implementing algorithms like the quicksort are prime examples of where recursion can shine.</p>
<p><strong>Example 1: Traversing a Tree-Like Structure</strong></p>
<p>Imagine you have a nested dictionary representing a file system hierarchy:</p>
<pre><code class="lang-python">file_system = {
    <span class="hljs-string">'documents'</span>: {
        <span class="hljs-string">'work'</span>: {<span class="hljs-string">'report.txt'</span>, <span class="hljs-string">'presentation.pptx'</span>},
        <span class="hljs-string">'personal'</span>: {<span class="hljs-string">'resume.pdf'</span>, <span class="hljs-string">'photo.jpg'</span>},
    },
    <span class="hljs-string">'music'</span>: {<span class="hljs-string">'song1.mp3'</span>, <span class="hljs-string">'song2.mp3'</span>},
}
</code></pre>
<p>A recursive function can easily traverse this structure:</p>
<pre><code>def print_files(directory):
    <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> directory:
        <span class="hljs-keyword">if</span> isinstance(directory[item], set):  # Base <span class="hljs-keyword">case</span>: it<span class="hljs-string">'s a file
            print(item)
        else:
            print_files(directory[item])  # Recursive call for subdirectories

print_files(file_system)</span>
</code></pre><p>Output: </p>
<pre><code class="lang-python">report.txt presentation.pptx resume.pdf photo.jpg song1.mp3 song2.mp3
</code></pre>
<p><strong>Example 2: Quicksort Algorithm (Sorting)</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">quicksort</span>(<span class="hljs-params">arr</span>):</span>
    <span class="hljs-keyword">if</span> len(arr) &lt; <span class="hljs-number">2</span>:  <span class="hljs-comment"># Base case: empty or single-element list</span>
        <span class="hljs-keyword">return</span> arr
    <span class="hljs-keyword">else</span>:
        pivot = arr[<span class="hljs-number">0</span>]
        less = [i <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> arr[<span class="hljs-number">1</span>:] <span class="hljs-keyword">if</span> i &lt;= pivot]
        greater = [i <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> arr[<span class="hljs-number">1</span>:] <span class="hljs-keyword">if</span> i &gt; pivot]
        <span class="hljs-keyword">return</span> quicksort(less) + [pivot] + quicksort(greater)

numbers = [<span class="hljs-number">29</span>, <span class="hljs-number">13</span>, <span class="hljs-number">72</span>, <span class="hljs-number">51</span>, <span class="hljs-number">8</span>, <span class="hljs-number">45</span>]
sorted_numbers = quicksort(numbers)
print(sorted_numbers)
</code></pre>
<h5 id="heading-when-to-opt-for-iteration">When to Opt for Iteration:</h5>
<p>If your problem doesn't exhibit this recursive structure, or if performance is a primary concern, iterative solutions are often the preferred choice.  Loops can generally handle such scenarios more efficiently.</p>
<p><strong>Example 1: Calculating Sum of Numbers</strong></p>
<pre><code>numbers = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
total = <span class="hljs-number">0</span>
<span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> numbers:
    total += num
print(total)  # Output: <span class="hljs-number">15</span>
</code></pre><p><strong>Example 2: Finding Maximum Value</strong></p>
<pre><code class="lang-python">numbers = [<span class="hljs-number">5</span>, <span class="hljs-number">12</span>, <span class="hljs-number">3</span>, <span class="hljs-number">9</span>, <span class="hljs-number">18</span>]
max_value = numbers[<span class="hljs-number">0</span>]  <span class="hljs-comment"># Start with the first element</span>
<span class="hljs-keyword">for</span> num <span class="hljs-keyword">in</span> numbers:
    <span class="hljs-keyword">if</span> num &gt; max_value:
        max_value = num
print(max_value)  <span class="hljs-comment"># Output: 18</span>
</code></pre>
<p><strong>Key Considerations:</strong></p>
<ul>
<li><strong>Recursive elegance:</strong> Recursion often leads to shorter, more elegant code when the problem's structure is inherently recursive (like trees or sorting).</li>
<li><strong>Iterative efficiency:</strong> Iteration tends to be more memory-efficient and performant, especially for large datasets or problems that don't naturally break down into recursive patterns.</li>
</ul>
<h5 id="heading-more-complex-code-example">More Complex Code Example:</h5>
<p><strong>Scenario:</strong> Calculating the total size of a directory and all its subdirectories.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> os

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_directory_size</span>(<span class="hljs-params">path</span>):</span>
    <span class="hljs-string">"""Recursively calculates the total size of a directory (in bytes)."""</span>

    total_size = <span class="hljs-number">0</span>

    <span class="hljs-comment"># Base Case: If the path is a file, return its size directly</span>
    <span class="hljs-keyword">if</span> os.path.isfile(path):
        <span class="hljs-keyword">return</span> os.path.getsize(path)

    <span class="hljs-comment"># Recursive Case: If the path is a directory, iterate over its contents</span>
    <span class="hljs-keyword">for</span> item <span class="hljs-keyword">in</span> os.listdir(path):
        item_path = os.path.join(path, item)

        <span class="hljs-comment"># Recursively call the function for each item (file or directory)</span>
        total_size += calculate_directory_size(item_path)

    <span class="hljs-keyword">return</span> total_size

directory_path = <span class="hljs-string">"/path/to/your/directory"</span>  <span class="hljs-comment"># Replace with the actual path</span>
total_size = calculate_directory_size(directory_path)
print(<span class="hljs-string">f"Total size of '<span class="hljs-subst">{directory_path}</span>': <span class="hljs-subst">{total_size}</span> bytes"</span>)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>The code starts by defining a function <code>calculate_directory_size</code>, which recursively calculates the total size of a directory.</li>
<li>If the given path is a file, it gets the size of the file using <code>os.path.getsize</code> and returns it.</li>
<li>If the given path is a directory, it iterates over all the items in the directory and calls the <code>calculate_directory_size</code> function recursively for each item.</li>
<li>The total size is updated by adding the size of each item. Finally, the total size of the directory is returned.</li>
<li>In the main part of the code, the user is prompted to enter the directory path. The <code>calculate_directory_size</code> function is then called with the provided directory path. The total size of the directory is printed to the console.</li>
</ul>
<p>This demonstrates recursion's usefulness in several ways:</p>
<ul>
<li><strong>Navigating Complex Structures:</strong> Directory structures are inherently hierarchical (tree-like). Recursion allows you to elegantly traverse this structure without needing complex loops or manual tracking of subdirectories.</li>
<li><strong>Conciseness:</strong> The recursive implementation is quite compact and expresses the logic in a way that closely mirrors how we think about directory sizes – the size of a directory is the sum of the sizes of its contents.</li>
<li><strong>Scalability:</strong> This function can handle arbitrarily deep directory hierarchies without modification. It naturally adapts to the structure of the data.</li>
</ul>
<p><strong>Key Points:</strong></p>
<ul>
<li><strong>Base Case:</strong> The function has a clear base case (<code>if os.path.isfile(path):</code>) to stop the recursion when it encounters a file.</li>
<li><strong>Recursive Step:</strong> The function recursively calls itself (<code>calculate_directory_size(item_path)</code>) to process subdirectories.</li>
<li><strong>Accumulator:</strong> The <code>total_size</code> variable acts as an accumulator, keeping track of the total size as the function traverses the directory tree.</li>
</ul>
<p>Recursion is a valuable tool in a Python developer's arsenal, offering elegance and conciseness in specific situations. But it's important to understand its limitations and potential pitfalls. </p>
<p>By carefully evaluating the problem at hand, you can make informed decisions about when to employ recursion and when to opt for alternative approaches.</p>
<h4 id="heading-decorators">Decorators</h4>
<p>Imagine decorators as elegant accessories for your Python functions, adding extra features or functionality without altering the core function's code. </p>
<p>In essence, a decorator is a function that takes another function as input, modifies its behavior, and returns a new, enhanced version of the original function.</p>
<p>This technique allows you to apply common behaviors, such as logging, timing, or authorization, to multiple functions without duplicating code. It's a powerful way to keep your code DRY (Don't Repeat Yourself) and promote a more modular and maintainable design.</p>
<h5 id="heading-simple-examples-of-decorators">Simple Examples of Decorators</h5>
<p>Let's explore two common use cases for decorators: timing function execution and adding logging capabilities.</p>
<p><strong>1. Timing Functions:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> time

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">timer</span>(<span class="hljs-params">func</span>):</span>  <span class="hljs-comment"># Decorator function</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        start_time = time.time()  <span class="hljs-comment"># Record start time</span>
        result = func(*args, **kwargs)  <span class="hljs-comment"># Call the original function</span>
        end_time = time.time()    <span class="hljs-comment"># Record end time</span>
        print(<span class="hljs-string">f"<span class="hljs-subst">{func.__name__}</span> took <span class="hljs-subst">{end_time - start_time:<span class="hljs-number">.2</span>f}</span> seconds to execute."</span>)
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@timer  # Applying the decorator to a function</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">slow_calculation</span>(<span class="hljs-params">n</span>):</span>
    <span class="hljs-string">"""Performs a slow calculation (for demonstration)."""</span>
    time.sleep(<span class="hljs-number">2</span>)  <span class="hljs-comment"># Simulate a 2-second delay</span>
    <span class="hljs-keyword">return</span> n**<span class="hljs-number">2</span>

slow_calculation(<span class="hljs-number">5</span>)  <span class="hljs-comment"># The output will also include timing information</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>timer</code> is the decorator function. It takes a function <code>func</code> as input.</li>
<li>Inside <code>timer</code>, a nested function <code>wrapper</code> is defined.</li>
<li><code>wrapper</code> measures the time it takes for <code>func</code> to execute and prints the result.</li>
<li>The <code>@timer</code> syntax above <code>slow_calculation</code> applies the decorator to that function.</li>
</ul>
<p><strong>2. Adding Logging:</strong></p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">logger</span>(<span class="hljs-params">func</span>):</span>  <span class="hljs-comment"># Decorator function</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">wrapper</span>(<span class="hljs-params">*args, **kwargs</span>):</span>
        print(<span class="hljs-string">f"Calling function: <span class="hljs-subst">{func.__name__}</span>"</span>)  <span class="hljs-comment"># Log before execution</span>
        result = func(*args, **kwargs)
        print(<span class="hljs-string">f"Finished executing: <span class="hljs-subst">{func.__name__}</span>"</span>)  <span class="hljs-comment"># Log after execution</span>
        <span class="hljs-keyword">return</span> result
    <span class="hljs-keyword">return</span> wrapper

<span class="hljs-meta">@logger  # Applying the decorator</span>
<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">greet</span>(<span class="hljs-params">name</span>):</span>
    print(<span class="hljs-string">f"Hello, <span class="hljs-subst">{name}</span>!"</span>)

greet(<span class="hljs-string">"Alice"</span>)  <span class="hljs-comment"># The output will also include log messages</span>
</code></pre>
<p>In this example, the <code>logger</code> decorator logs messages before and after the decorated function (<code>greet</code>) executes.</p>
<p><strong>Key Takeaways:</strong></p>
<ul>
<li>Decorators are a powerful tool for extending function behavior without modifying the function's code directly.</li>
<li>They are often used to apply common functionalities like logging, timing, and authentication to multiple functions.</li>
<li>The <code>@decorator_name</code> syntax provides a clean way to apply decorators to functions.</li>
</ul>
<p>Decorators open up a world of possibilities for customizing and enhancing your Python functions. As you progress in your programming journey, you'll discover even more advanced use cases for decorators, allowing you to create more expressive, maintainable, and feature-rich code.</p>
<h4 id="heading-python-functions-best-practices-and-tips">Python Functions Best Practices and Tips</h4>
<p>To truly wield the power of functions in your Python projects, it's essential to embrace best practices that enhance code readability, maintainability, and robustness. Let's delve into these principles and elevate your function-writing skills to the next level.</p>
<h5 id="heading-naming-conventions-clarity-and-consistency">Naming Conventions: Clarity and Consistency</h5>
<p>Clear, descriptive function names are like signposts in your code, guiding you and others through its logic. Adhering to the PEP 8 style guide ensures consistency and readability:</p>
<p><strong>Use lowercase:</strong> Function names should be lowercase, with words separated by underscores (for example, <code>calculate_average</code>, <code>process_data</code>).</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_mean</span>(<span class="hljs-params">data</span>):</span>
    <span class="hljs-comment"># function logic</span>
</code></pre>
<p><strong>Be descriptive:</strong> Choose names that accurately reflect the function's purpose. Avoid generic names like <code>f1</code> or <code>my_function</code>.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">filter_by_date_range</span>(<span class="hljs-params">data, start_date, end_date</span>):</span>
    <span class="hljs-comment"># function logic</span>
</code></pre>
<p><strong>Verbs:</strong> Start function names with verbs to convey action (e.g., <code>get_data</code>, <code>filter_results</code>).</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">generate_report</span>(<span class="hljs-params">data</span>):</span>
    <span class="hljs-comment"># function logic</span>
</code></pre>
<h5 id="heading-modularity-divide-and-conquer">Modularity: Divide and Conquer</h5>
<p>Breaking down complex tasks into smaller, focused functions is a cornerstone of good software design. This modular approach offers several benefits:</p>
<p><strong>Easier Testing:</strong> Smaller functions are simpler to test individually, leading to more reliable code.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">validate_input</span>(<span class="hljs-params">user_input</span>):</span>
    <span class="hljs-comment"># input validation logic</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">process_valid_data</span>(<span class="hljs-params">data</span>):</span>
    <span class="hljs-comment"># data processing logic</span>
</code></pre>
<p><strong>Code Reuse:</strong> Modular functions can be reused in different parts of your project, reducing redundancy.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_statistics</span>(<span class="hljs-params">data</span>):</span>
    <span class="hljs-comment"># function to calculate mean, median, mode, etc.</span>

sales_stats = calculate_statistics(sales_data)
customer_stats = calculate_statistics(customer_data)
</code></pre>
<p><strong>Improved Collaboration:</strong> Modular code is easier for multiple developers to work on simultaneously.</p>
<h5 id="heading-single-responsibility-principle-one-function-one-job">Single Responsibility Principle: One Function, One Job</h5>
<p>The Single Responsibility Principle (SRP) states that each function should have a single, well-defined purpose. Functions that try to do too much become complex, difficult to understand, and prone to errors.</p>
<p><strong>Focus:</strong> Keep your functions focused on a single task.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">clean_data</span>(<span class="hljs-params">data</span>):</span>
    <span class="hljs-comment"># data cleaning steps</span>

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">analyze_data</span>(<span class="hljs-params">data</span>):</span>
    <span class="hljs-comment"># data analysis steps</span>
</code></pre>
<p><strong>Cohesion:</strong> Group related actions together within a function.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">preprocess_image</span>(<span class="hljs-params">image</span>):</span>
    <span class="hljs-comment"># resize, normalize, and augment the image</span>
</code></pre>
<p><strong>Loose Coupling:</strong> Minimize dependencies between functions.</p>
<h5 id="heading-docstrings-your-codes-user-manual">Docstrings: Your Code's User Manual</h5>
<p>Docstrings are brief descriptions that provide valuable information about your functions. They should include:</p>
<ul>
<li><strong>Purpose:</strong> What does the function do?</li>
<li><strong>Arguments:</strong> What are the parameters, their types, and their meanings?</li>
<li><strong>Return Value:</strong> What does the function return, if anything?</li>
<li><strong>Examples:</strong> How to use the function with sample inputs and outputs.</li>
</ul>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">calculate_discount</span>(<span class="hljs-params">price, discount_percentage</span>):</span>
    <span class="hljs-string">"""
    Calculates the discounted price.

    Args:
        price: The original price of the item.
        discount_percentage: The discount percentage as a decimal (e.g., 0.15 for 15%).

    Returns:
        The discounted price.
    """</span>
    discount_amount = price * discount_percentage
    <span class="hljs-keyword">return</span> price - discount_amount
</code></pre>
<p>Well-documented code is easier to understand, use, and maintain. Use tools like Sphinx to automatically generate documentation from your docstrings.</p>
<h5 id="heading-testing-ensuring-function-reliability">Testing: Ensuring Function Reliability</h5>
<p>Thoroughly testing your functions is essential to catching errors early and ensuring the reliability of your code. Consider using automated testing frameworks like <code>pytest</code> or <code>unittest</code> to write and execute tests for your functions.</p>
<p><strong>Unit Tests:</strong> Test individual functions in isolation.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> unittest

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestCalculateDiscount</span>(<span class="hljs-params">unittest.TestCase</span>):</span>
    <span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_15_percent_discount</span>(<span class="hljs-params">self</span>):</span>
        result = calculate_discount(<span class="hljs-number">100</span>, <span class="hljs-number">0.15</span>)
        self.assertEqual(result, <span class="hljs-number">85.0</span>)
</code></pre>
<p><strong>Integration Tests:</strong> Test how functions work together.</p>
<p><strong>Edge Cases:</strong> Test functions with unusual or extreme inputs to ensure they handle them gracefully.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">test_zero_discount</span>(<span class="hljs-params">self</span>):</span>
    result = calculate_discount(<span class="hljs-number">100</span>, <span class="hljs-number">0.0</span>)
    self.assertEqual(result, <span class="hljs-number">100.0</span>)  <span class="hljs-comment"># No discount expected</span>
</code></pre>
<p>By embracing these best practices and dedicating time to testing, you'll be well on your way to becoming a Python expert capable of producing high-quality, reliable, and maintainable code. Remember, writing good code is an investment that pays dividends in the long run.</p>
<h3 id="heading-16-modules-and-packages">1.6 Modules and Packages:</h3>
<p>The true power of Python lies not only in its core language but also in its vast ecosystem of pre-built modules and packages. Think of these as specialized toolkits, each designed to streamline specific tasks, from mathematical calculations to data manipulation and visualization. </p>
<p>By harnessing the capabilities of these external libraries, you can drastically accelerate your data analysis workflows and unlock a world of possibilities.</p>
<h4 id="heading-importing-modules-accessing-pythons-built-in-power">Importing Modules: Accessing Python's Built-in Power</h4>
<p>Python comes bundled with a rich collection of modules, each offering a set of functions, classes, and variables tailored to specific domains. </p>
<p>Need to perform mathematical operations? The <code>math</code> module has you covered. Want to generate random numbers for simulations or experiments? Look no further than the <code>random</code> module.</p>
<p>To access the functionality within a module, you use the <code>import</code> statement:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> math
print(math.pi)    <span class="hljs-comment"># Output: 3.141592653589793</span>
print(math.sqrt(<span class="hljs-number">16</span>))  <span class="hljs-comment"># Output: 4.0</span>
</code></pre>
<p>In this example, we import the <code>math</code> module and then use dot notation to access its constants and functions.</p>
<h4 id="heading-working-with-external-packages-supercharging-your-data-analysis">Working with External Packages: Supercharging Your Data Analysis</h4>
<p>External packages, often distributed through the Python Package Index (PyPI), extend Python's capabilities even further. For data science and analysis, two of the most essential packages are:</p>
<ul>
<li><strong>Pandas:</strong> A powerhouse for data manipulation and analysis, providing data structures like DataFrames and Series that simplify working with tabular data.</li>
<li><strong>NumPy:</strong> The foundation of numerical computing in Python, offering efficient operations on arrays and matrices, making it essential for scientific and data-intensive tasks.</li>
</ul>
<p>To install external packages, you typically use the <code>pip</code> package manager:</p>
<pre><code class="lang-python">pip install pandas numpy
</code></pre>
<p>Once installed, you can import them into your code:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># ... use pandas and numpy for data analysis</span>
</code></pre>
<p><strong>Pro Tip:</strong> Aliasing packages with shorter names (like <code>pd</code> for pandas) is a common convention to make your code more concise.</p>
<h4 id="heading-key-takeaway">Key Takeaway</h4>
<p>Python's modules and packages are your secret weapons for efficient and effective data analysis. By tapping into this vast ecosystem, you can leverage the work of countless developers who have already solved common problems, freeing you to focus on your unique analysis goals.</p>
<h3 id="heading-17-error-handling">1.7 Error Handling:</h3>
<p>In the world of programming, even the most carefully crafted code can encounter unexpected roadblocks—errors. These can arise from invalid user input, file-reading issues, network failures, or even simple typos. That's why having a robust error handling strategy is essential. </p>
<p>Python provides powerful mechanisms to gracefully manage these errors, ensuring your programs don't crash unexpectedly and can recover from adverse situations.</p>
<h4 id="heading-try-except-blocks-your-safety-net">Try-Except Blocks: Your Safety Net</h4>
<p>The <code>try-except</code> block is your first line of defense against errors. It allows you to isolate code that might raise an exception and specify how to handle that exception if it occurs. This provides a structured way to respond to errors and prevent your program from abruptly terminating.</p>
<pre><code class="lang-python"><span class="hljs-keyword">try</span>:
    result = <span class="hljs-number">10</span> / <span class="hljs-number">0</span>  <span class="hljs-comment"># This will raise a ZeroDivisionError</span>
<span class="hljs-keyword">except</span> ZeroDivisionError:
    print(<span class="hljs-string">"Error: Division by zero is not allowed."</span>)
</code></pre>
<p>In this example, the code within the <code>try</code> block attempts to divide by zero, which is an invalid operation. The <code>except</code> block catches the resulting <code>ZeroDivisionError</code> and prints an informative error message instead of letting the program crash.</p>
<h4 id="heading-raising-exceptions-signaling-problems">Raising Exceptions: Signaling Problems</h4>
<p>Sometimes, you might need to explicitly raise an exception to indicate that something has gone wrong in your code. You can do this using the <code>raise</code> statement, followed by the exception type and an optional error message.</p>
<pre><code class="lang-python"><span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">validate_age</span>(<span class="hljs-params">age</span>):</span>
    <span class="hljs-keyword">if</span> age &lt; <span class="hljs-number">0</span>:
        <span class="hljs-keyword">raise</span> ValueError(<span class="hljs-string">"Age cannot be negative."</span>)

<span class="hljs-keyword">try</span>:
    validate_age(<span class="hljs-number">-5</span>)
<span class="hljs-keyword">except</span> ValueError <span class="hljs-keyword">as</span> e:
    print(e)  <span class="hljs-comment"># Output: Age cannot be negative.</span>
</code></pre>
<p>In this code snippet, the <code>validate_age</code> function raises a <code>ValueError</code> if the provided age is negative. The <code>try-except</code> block handles this exception and prints the error message.</p>
<p><strong>Key Takeaways:</strong></p>
<ul>
<li><strong>Anticipate Errors:</strong> Think about the potential errors your code might encounter and use <code>try-except</code> blocks to handle them gracefully.</li>
<li><strong>Be Specific:</strong> Catch specific exception types (<code>ZeroDivisionError</code>, <code>TypeError</code>, <code>ValueError</code>, and so on) to provide targeted error handling.</li>
<li><strong>Custom Exceptions:</strong> Consider creating your own custom exception classes for more specialized error handling.</li>
<li><strong>Logging:</strong> Use logging modules to record error messages and relevant information for later analysis.</li>
</ul>
<p>By incorporating error handling techniques into your Python code, you can create more robust, reliable, and user-friendly programs. Don't let unexpected errors derail your data analysis projects—be prepared and ensure your code gracefully handles any challenges that come its way.</p>
<h2 id="heading-2-essential-python-libraries-for-data-wrangling">2. Essential Python Libraries for Data Wrangling</h2>
<p>Welcome to the toolkit that will revolutionize the way you handle, analyze, and gain insights from data. In this chapter, I'll introduce you to the dynamic trio that forms the backbone of Python's data science prowess: Pandas, NumPy, and Matplotlib.</p>
<p>In the data-driven world, where insights are the currency of success, these libraries offer a powerful arsenal to conquer the challenges of messy, complex datasets. Whether you're cleaning and transforming raw data, performing intricate calculations, or crafting compelling visualizations, these tools are indispensable assets in your data analyst's toolkit.</p>
<p><a target="_blank" href="https://pandas.pydata.org/">Pandas</a>, with its intuitive Series and DataFrame structures, empowers you to organize and manipulate data effortlessly. You'll master the art of filtering, sorting, aggregating, and transforming data to uncover hidden patterns and relationships.</p>
<p><a target="_blank" href="https://numpy.org/">NumPy's</a> high-performance numerical arrays and mathematical operations provide the engine for your data-crunching needs. You'll perform lightning-fast calculations on vast datasets, enabling you to tackle even the most computationally intensive tasks.</p>
<p><a target="_blank" href="https://matplotlib.org/">Matplotlib</a>, the visualization virtuoso, will elevate your storytelling with data. You'll learn to create a wide array of plots, from simple line charts to informative histograms, and customize them to perfection, ensuring your data communicates its story clearly and effectively.</p>
<p>By mastering these libraries, you'll transform yourself into a data wrangling expert, capable of effortlessly extracting valuable insights from even the most unruly datasets.  Your journey toward data-driven mastery continues—let's dive into the details of these powerful tools.</p>
<h3 id="heading-21-pandas">2.1 Pandas</h3>
<p>Pandas emerges as a fundamental pillar in the data analyst's toolkit, renowned for its intuitive and versatile capabilities in managing, manipulating, and extracting insights from structured data. Its core data structures, Series and DataFrames, provide a robust foundation for handling tabular data with ease and efficiency, making it an essential library for data professionals across industries.</p>
<h4 id="heading-real-world-applications-of-pandas">Real-World Applications of Pandas</h4>
<p>In the world of data-driven decision-making, Pandas is a game-changer. Here are some examples of how this powerhouse library is used:</p>
<p><strong>Finance:</strong> Investment firms and hedge funds use Pandas to analyze stock market data, calculate portfolio risk, and develop trading strategies.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Read stock data from a CSV file</span>
stock_data = pd.read_csv(<span class="hljs-string">"stock_prices.csv"</span>)

<span class="hljs-comment"># Calculate daily returns</span>
stock_data[<span class="hljs-string">"Daily_Return"</span>] = stock_data[<span class="hljs-string">"Close"</span>].pct_change()
</code></pre>
<p><strong>Marketing:</strong> Marketing teams employ Pandas to analyze customer behavior, segment audiences, and optimize advertising campaigns.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Group customers by age and calculate average purchase amount</span>
customer_segments = customer_data.groupby(<span class="hljs-string">"Age"</span>)[<span class="hljs-string">"PurchaseAmount"</span>].mean()
</code></pre>
<p><strong>Healthcare:</strong> Researchers utilize Pandas to analyze clinical trial data, identify patterns in patient outcomes, and develop predictive models for diseases.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Filter patient data for a specific condition</span>
subset = patient_data[patient_data[<span class="hljs-string">"Condition"</span>] == <span class="hljs-string">"Diabetes"</span>]
</code></pre>
<p><strong>E-commerce:</strong> Online retailers use Pandas to analyze sales data, recommend products to customers, and optimize pricing strategies.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Find the top 10 best-selling products</span>
top_products = sales_data[<span class="hljs-string">"Product"</span>].value_counts().head(<span class="hljs-number">10</span>)
</code></pre>
<p>Its comprehensive suite of functions empowers analysts to perform intricate data transformations, including:</p>
<ul>
<li><strong>Filtering:</strong> Selecting specific rows or columns based on conditions.</li>
</ul>
<pre><code class="lang-python">high_income_customers = customer_data[customer_data[<span class="hljs-string">"Income"</span>] &gt; <span class="hljs-number">100000</span>]
</code></pre>
<ul>
<li><strong>Sorting:</strong> Ordering data based on values in one or more columns.</li>
</ul>
<pre><code class="lang-python">sorted_data = sales_data.sort_values(by=<span class="hljs-string">"Date"</span>, ascending=<span class="hljs-literal">False</span>)
</code></pre>
<ul>
<li><strong>Aggregating:</strong> Combining data across rows or columns using functions like <code>sum</code>, <code>mean</code>, <code>count</code>, etc.</li>
</ul>
<pre><code class="lang-python">total_sales_by_region = sales_data.groupby(<span class="hljs-string">"Region"</span>)[<span class="hljs-string">"Sales"</span>].sum()
</code></pre>
<ul>
<li><strong>Reshaping:</strong> Pivoting or melting data to rearrange its structure.</li>
</ul>
<pre><code class="lang-python">pivoted_data = sales_data.pivot_table(values=<span class="hljs-string">"Sales"</span>, index=<span class="hljs-string">"Date"</span>, columns=<span class="hljs-string">"Product"</span>)
</code></pre>
<p>And Pandas excels at data cleaning, adeptly handling:</p>
<ul>
<li><strong>Missing Values:</strong> Identifying and imputing missing data.</li>
</ul>
<pre><code class="lang-python">customer_data.fillna(customer_data.mean(), inplace=<span class="hljs-literal">True</span>)
</code></pre>
<ul>
<li><strong>Outliers:</strong> Detecting and removing or adjusting extreme values.</li>
</ul>
<pre><code class="lang-python">sales_data = sales_data[(sales_data[<span class="hljs-string">"Price"</span>] &gt; <span class="hljs-number">10</span>) &amp; (sales_data[<span class="hljs-string">"Price"</span>] &lt; <span class="hljs-number">1000</span>)]
</code></pre>
<ul>
<li><strong>Inconsistencies:</strong>  Standardizing data formats and correcting errors.</li>
</ul>
<pre><code class="lang-python">sales_data[<span class="hljs-string">"Date"</span>] = pd.to_datetime(sales_data[<span class="hljs-string">"Date"</span>], format=<span class="hljs-string">"%Y-%m-%d"</span>)
</code></pre>
<p>Pandas also offers a wealth of functions designed for exploratory data analysis (EDA), allowing analysts to gain valuable insights into the structure, distributions, and relationships within their datasets.</p>
<p>In this chapter, we'll explore Pandas' core features and functionalities, equipping you with the skills to navigate its extensive capabilities. You'll delve into its data structures, master data manipulation techniques, and acquire proficiency in data cleaning and exploratory analysis. </p>
<h3 id="heading-series-and-dataframes">Series and DataFrames</h3>
<p>Imagine your data as a collection of puzzle pieces. Series and DataFrames, the core data structures of Pandas, are the frameworks that help you assemble these pieces into a meaningful whole. They provide a powerful and intuitive way to organize, manipulate, and analyze your data, whether it's a simple list of numbers or a complex table with multiple columns.</p>
<h4 id="heading-series-a-single-column-of-data">Series: A Single Column of Data</h4>
<p>Think of a Series as a single column in a spreadsheet. It's a one-dimensional labeled array that can hold data of any type—numbers, strings, booleans, or even Python objects. Each value in a Series is associated with an index, which serves as a unique identifier for the value.</p>
<p><strong>Creating a Series:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Create a Series from a list</span>
data = pd.Series([<span class="hljs-number">10</span>, <span class="hljs-number">20</span>, <span class="hljs-number">30</span>, <span class="hljs-number">40</span>])

<span class="hljs-comment"># Accessing elements</span>
print(data[<span class="hljs-number">0</span>])  <span class="hljs-comment"># Output: 10</span>
print(data[<span class="hljs-number">2</span>])  <span class="hljs-comment"># Output: 30</span>
</code></pre>
<h4 id="heading-dataframes-tabular-data-made-easy">DataFrames: Tabular Data Made Easy</h4>
<p>A DataFrame is the star of the Pandas show. It's a two-dimensional table-like structure with rows and columns, similar to a spreadsheet or a SQL table. Each column in a DataFrame is a Series, and you can think of a DataFrame as a collection of Series that share the same index.</p>
<p><strong>Creating a DataFrame:</strong></p>
<pre><code class="lang-python">data = {<span class="hljs-string">'Name'</span>: [<span class="hljs-string">'Alice'</span>, <span class="hljs-string">'Bob'</span>, <span class="hljs-string">'Charlie'</span>],
        <span class="hljs-string">'Age'</span>: [<span class="hljs-number">25</span>, <span class="hljs-number">30</span>, <span class="hljs-number">35</span>],
        <span class="hljs-string">'City'</span>: [<span class="hljs-string">'New York'</span>, <span class="hljs-string">'London'</span>, <span class="hljs-string">'Paris'</span>]}
df = pd.DataFrame(data)
print(df)
</code></pre>
<p><strong>Output:</strong></p>
<pre><code class="lang-python">      Name  Age       City
<span class="hljs-number">0</span>    Alice   <span class="hljs-number">25</span>  New York
<span class="hljs-number">1</span>      Bob   <span class="hljs-number">30</span>     London
<span class="hljs-number">2</span>  Charlie   <span class="hljs-number">35</span>      Paris
</code></pre>
<p><strong>Accessing Elements:</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Accessing a column</span>
print(df[<span class="hljs-string">'Age'</span>])
print(df.Age)

<span class="hljs-comment"># Accessing a row</span>
print(df.iloc[<span class="hljs-number">1</span>])
</code></pre>
<h4 id="heading-the-power-of-series-and-dataframes">The Power of Series and DataFrames</h4>
<p>Series and DataFrames are not just containers for your data. They come packed with powerful features for data manipulation and analysis. Here are some key capabilities:</p>
<ul>
<li><strong>Indexing and Slicing:</strong> Select specific elements or subsets of your data with ease.</li>
<li><strong>Filtering:</strong> Extract rows or columns based on conditions.</li>
<li><strong>Aggregation:</strong> Perform calculations (sum, mean, median, and so on) on your data.</li>
<li><strong>Merging and Joining:</strong> Combine multiple DataFrames based on shared columns.</li>
<li><strong>Time Series Analysis:</strong> Handle time-indexed data with specialized tools.</li>
</ul>
<h3 id="heading-data-manipulation">Data Manipulation</h3>
<p>Transforming raw data into meaningful insights is the cornerstone of data analysis. Pandas empowers you with a robust set of tools to filter, sort, aggregate, and reshape your data, turning it into a treasure trove of information ready for deeper exploration and decision-making.</p>
<h4 id="heading-filtering-zeroing-in-on-the-data-you-need">Filtering: Zeroing in on the Data You Need</h4>
<p>Imagine having a magnifying glass that lets you pinpoint the exact data points you need. Pandas filtering does just that. It allows you to select specific rows or columns based on conditions you define.</p>
<p>For example, if you have a DataFrame containing sales data, you can easily filter for all transactions made in a specific region or by a particular customer segment. This focused view enables you to analyze trends, identify outliers, and uncover hidden patterns within specific subsets of your data.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Filter for transactions in the 'West' region</span>
western_sales = sales_data[sales_data[<span class="hljs-string">'Region'</span>] == <span class="hljs-string">'West'</span>]
</code></pre>
<h4 id="heading-sorting-organizing-your-data-for-clarity">Sorting: Organizing Your Data for Clarity</h4>
<p>Sorting is like arranging your books on a shelf – it brings order and structure to your data. Pandas provides flexible sorting capabilities, allowing you to sort your DataFrame by one or more columns in ascending or descending order.</p>
<p>For instance, you can sort customer data by purchase date to see your most recent transactions or sort product data by sales volume to identify your top-performing items. Sorted data provides a clearer picture of relationships and trends, making it easier to draw meaningful conclusions.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sort sales data by date in descending order</span>
sorted_sales = sales_data.sort_values(by=<span class="hljs-string">'Date'</span>, ascending=<span class="hljs-literal">False</span>)
</code></pre>
<h4 id="heading-aggregating-unveiling-summary-statistics">Aggregating: Unveiling Summary Statistics</h4>
<p>Aggregation is the art of summarizing your data. With Pandas, you can quickly calculate essential statistics like sums, means, medians, and counts across rows or columns.</p>
<p>For example, you can aggregate sales data to find the total revenue generated by each product category or calculate the average customer age within different demographics.  These aggregated metrics offer valuable insights into your data's central tendencies and distributions.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Calculate total sales by product category</span>
total_sales_by_category = sales_data.groupby(<span class="hljs-string">'Category'</span>)[<span class="hljs-string">'Sales'</span>].sum()
</code></pre>
<h4 id="heading-transforming-reshaping-your-data-for-analysis">Transforming: Reshaping Your Data for Analysis</h4>
<p>Sometimes, your data needs a makeover to fit your analytical needs. Pandas offers a wide range of transformation functions for reshaping your data.</p>
<p>You can pivot your data to summarize values by different criteria, melt it to convert wide-format data to long format, or even create new columns based on calculations or transformations applied to existing columns. These transformations open up new avenues for exploration and analysis.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Pivot sales data to show sales by product and region</span>
sales_pivot = sales_data.pivot_table(values=<span class="hljs-string">'Sales'</span>, index=<span class="hljs-string">'Product'</span>, columns=<span class="hljs-string">'Region'</span>)
</code></pre>
<h4 id="heading-embrace-the-power-of-pandas">Embrace the Power of Pandas</h4>
<p>By mastering these data manipulation techniques, you'll gain the ability to extract meaningful insights from your data quickly and efficiently. Pandas is your versatile partner in the quest for data-driven decision-making.</p>
<p>Remember, effective data analysis isn't just about having data – it's about knowing how to wield it. With Pandas, you'll be well-equipped to uncover the hidden patterns, trends, and opportunities that lie within your datasets, empowering you to make informed choices that drive your organization forward.</p>
<h4 id="heading-213-data-cleaning">2.1.3 Data Cleaning</h4>
<p>Real-world data is rarely perfect. It's often riddled with missing values, outliers that skew your analysis, and inconsistencies that can undermine your conclusions. Data scientists often feel that cleaning and preparing data is the most time-consuming part of their job. But fear not, Pandas is your trusted ally in this essential task.</p>
<h5 id="heading-taming-missing-values-the-art-of-imputation">Taming Missing Values: The Art of Imputation</h5>
<p>Missing values are like blank spaces in a puzzle – they obscure the complete picture.  </p>
<p>Pandas offers several strategies to fill those gaps:</p>
<p><strong>Deletion:</strong> If missing values are relatively few, you can simply drop rows or columns containing them. Use with caution, as you might lose valuable information.</p>
<pre><code class="lang-python">df.dropna(inplace=<span class="hljs-literal">True</span>)  <span class="hljs-comment"># Drop rows with any missing values</span>
</code></pre>
<p><strong>Imputation:</strong> Fill missing values with a reasonable estimate, such as the mean, median, or mode of the column.</p>
<pre><code>df[<span class="hljs-string">'Age'</span>].fillna(df[<span class="hljs-string">'Age'</span>].mean(), inplace=True)  # Fill <span class="hljs-keyword">with</span> mean age
</code></pre><p><strong>Interpolation:</strong> For time-series data, estimate missing values based on neighboring values.</p>
<pre><code class="lang-python">df[<span class="hljs-string">'Temperature'</span>].interpolate(method=<span class="hljs-string">'linear'</span>, inplace=<span class="hljs-literal">True</span>)
</code></pre>
<h5 id="heading-outlier-detection-and-handling-maintaining-data-integrity">Outlier Detection and Handling: Maintaining Data Integrity</h5>
<p>Outliers are like rogue data points that don't fit the typical pattern. While they can offer valuable insights, they can also distort your analysis. Pandas provides tools to identify and handle outliers:</p>
<ol>
<li><strong>Statistical Methods:</strong> Use z-scores or interquartile range (IQR) to detect outliers based on standard deviations from the mean.</li>
<li><strong>Visualization:</strong> Box plots and scatter plots can visually reveal outliers.</li>
<li><strong>Winsorization:</strong> Cap outliers at a certain percentile to reduce their impact.</li>
</ol>
<pre><code class="lang-python"><span class="hljs-comment"># Remove outliers using IQR</span>
Q1 = df[<span class="hljs-string">'Price'</span>].quantile(<span class="hljs-number">0.25</span>)
Q3 = df[<span class="hljs-string">'Price'</span>].quantile(<span class="hljs-number">0.75</span>)
IQR = Q3 - Q1
df = df[~((df[<span class="hljs-string">'Price'</span>] &lt; (Q1 - <span class="hljs-number">1.5</span> * IQR)) | (df[<span class="hljs-string">'Price'</span>] &gt; (Q3 + <span class="hljs-number">1.5</span> * IQR)))]
</code></pre>
<h5 id="heading-ensuring-consistency-standardizing-your-data">Ensuring Consistency: Standardizing Your Data</h5>
<p>Inconsistent data formats can hinder analysis. Pandas enables you to standardize data types, correct typos, and resolve inconsistencies, ensuring your data is clean and ready for analysis.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Convert 'Date' column to datetime format</span>
df[<span class="hljs-string">'Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Date'</span>])

<span class="hljs-comment"># Replace inconsistent category names</span>
df[<span class="hljs-string">'Category'</span>] = df[<span class="hljs-string">'Category'</span>].replace({<span class="hljs-string">'Mens'</span>:<span class="hljs-string">'Men'</span>, <span class="hljs-string">'Womens'</span>:<span class="hljs-string">'Women'</span>})
</code></pre>
<p>Data cleaning is not a glamorous task, but it's a crucial one – and you should embrace it. Investing time in cleaning your data will pay dividends in the accuracy and reliability of your analysis.</p>
<p><strong>Remember:</strong> Garbage in, garbage out. Clean data is the foundation of sound decision-making.</p>
<h4 id="heading-214-data-exploration">2.1.4 Data Exploration</h4>
<p>The initial exploration of a dataset is akin to a detective's first steps at a crime scene. You're seeking clues, patterns, and anomalies that hint at the hidden story within your data. Pandas, your trusted investigative partner, provides a robust toolkit for this crucial phase of data analysis.</p>
<h5 id="heading-unlocking-insights-with-pandas-functions">Unlocking Insights with Pandas Functions</h5>
<p>Pandas offers a wealth of functions designed to illuminate your data's essential characteristics:</p>
<ul>
<li><strong><code>df.head()</code> and <code>df.tail()</code>:</strong>  These functions offer a quick glimpse into your data, revealing the first or last few rows of your DataFrame. This is your initial "hello" to the dataset, providing a sense of its structure and content.</li>
<li><strong><code>df.info()</code>:</strong> Gain a high-level overview of your data, including column names, data types, and the number of non-null values. This is like checking the inventory at the crime scene – understanding what you're working with.</li>
<li><strong><code>df.describe()</code>:</strong> Uncover key statistical summaries of your numerical columns, such as mean, median, standard deviation, and quartiles. This is your statistical snapshot, revealing central tendencies and variability.</li>
<li><strong><code>df.value_counts()</code>:</strong> For categorical columns, this function reveals the frequency of each unique value, giving you a sense of the distribution of your data.</li>
<li><strong><code>df.corr()</code>:</strong> Calculate correlations between numerical columns to identify potential relationships and dependencies. This is like finding fingerprints at the scene – evidence of connections within the data.</li>
<li><strong>Visualization:</strong> Pandas seamlessly integrates with visualization libraries like Matplotlib and Seaborn, allowing you to create informative plots to further explore your data. Histograms, scatter plots, and bar charts are just a few examples of visualizations that can reveal patterns, outliers, and distributions.</li>
</ul>
<h5 id="heading-the-power-of-exploratory-data-analysis-eda">The Power of Exploratory Data Analysis (EDA)</h5>
<p>Investing time in EDA is not merely a preliminary step – it's a critical phase that can save you hours of frustration down the line.</p>
<p>Data scientists spend a lot of their time on data cleaning and preparation, including EDA. This investment pays off by ensuring your analysis is accurate, your models are robust, and your insights are meaningful.</p>
<p><strong>Practical Advice:</strong></p>
<ul>
<li><strong>Start with EDA:</strong> Don't rush into modeling or complex analysis. Take the time to thoroughly understand your data's structure and characteristics.</li>
<li><strong>Ask Questions:</strong> What are the ranges of your variables? Are there any missing values? How are different variables related?</li>
<li><strong>Visualize:</strong> Don't just rely on numbers. Use plots and charts to gain visual insights into your data.</li>
<li><strong>Iterate:</strong> EDA is often an iterative process. As you uncover new insights, you may need to revisit earlier steps to refine your understanding.</li>
</ul>
<p>Pandas is your trusted guide in the world of data exploration. By leveraging its powerful functions and visualization capabilities, you'll be well on your way to uncovering the stories your data has to tell. And remember, the most insightful discoveries often emerge from the simplest explorations.</p>
<h3 id="heading-22-numpy">2.2 NumPy:</h3>
<p>In the realm of data science, where efficiency and precision are paramount, NumPy emerges as a game-changer, providing the computational muscle to handle the most demanding analytical tasks.  </p>
<p>By harnessing the power of optimized data structures and vectorized operations, NumPy propels your data analysis to unprecedented speeds, enabling you to extract valuable insights in a fraction of the time.</p>
<ul>
<li><strong>Efficient Data Handling:</strong> NumPy's <code>ndarray</code> (n-dimensional array) is designed for performance, storing homogeneous data (elements of the same type) to enable rapid calculations.</li>
<li><strong>Lightning-Fast Calculations:</strong> NumPy's optimized algorithms and memory management significantly outperform standard Python lists, often making calculations up to 50 times faster.</li>
<li><strong>Intuitive Syntax and Robust Functionality:</strong> Whether you're a seasoned data scientist or just starting your journey, NumPy's ease of use and powerful features make it an accessible yet indispensable tool.</li>
<li><strong>Vast Applications:</strong> NumPy's capabilities extend across various domains, from finance and research to machine learning and beyond.</li>
<li><strong>Your Secret Weapon:</strong> By mastering NumPy, you gain a competitive advantage in the data-driven world, unlocking a new level of computational prowess.</li>
</ul>
<p>In this chapter, you'll delve into the heart of NumPy, exploring its core data structure, the <code>ndarray</code>, and discovering how to leverage its powerful mathematical operations.</p>
<h4 id="heading-221-arrays">2.2.1 Arrays</h4>
<p>Tired of waiting for your data calculations to finish? NumPy's <code>ndarray</code> (n-dimensional array) is your solution for lightning-fast numerical operations. </p>
<p>Unlike Python's built-in lists, which can be slow when dealing with large datasets, NumPy arrays are optimized for speed and efficiency. They can offer big performance boosts when used correctly.</p>
<p><strong>Why NumPy Arrays?</strong></p>
<ul>
<li><strong>Speed:</strong> NumPy's underlying C implementation and vectorized operations enable it to process data much faster than Python lists, especially for large datasets.</li>
<li><strong>Memory Efficiency:</strong> NumPy arrays store elements of the same type contiguously in memory, reducing overhead and improving memory utilization compared to lists.</li>
<li><strong>Convenience:</strong> NumPy provides a wealth of functions for working with arrays, making common tasks like filtering, sorting, and aggregating a breeze.</li>
<li><strong>Broadcasting:</strong> NumPy automatically handles operations between arrays of different shapes, simplifying complex calculations.</li>
<li><strong>Linear Algebra:</strong> NumPy offers extensive support for linear algebra operations, making it essential for scientific and engineering applications.</li>
</ul>
<h5 id="heading-unlocking-the-power-of-numpy-arrays">Unlocking the Power of NumPy Arrays</h5>
<p>Let's see NumPy arrays in action with a few examples:</p>
<p><strong>Example 1: Basic Array Operations</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Create an array from a list</span>
data = np.array([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>])

<span class="hljs-comment"># Element-wise operations</span>
doubled = data * <span class="hljs-number">2</span>  
squared = data ** <span class="hljs-number">2</span>
print(doubled)  <span class="hljs-comment"># Output: [ 2  4  6  8 10]</span>
print(squared)  <span class="hljs-comment"># Output: [ 1  4  9 16 25]</span>

<span class="hljs-comment"># Filtering</span>
filtered = data[data &gt; <span class="hljs-number">2</span>]
print(filtered)  <span class="hljs-comment"># Output: [3 4 5]</span>
</code></pre>
<p><strong>Example 2: Statistical Analysis</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Calculate mean and standard deviation</span>
data = np.array([<span class="hljs-number">12</span>, <span class="hljs-number">15</span>, <span class="hljs-number">8</span>, <span class="hljs-number">11</span>, <span class="hljs-number">20</span>])
mean = np.mean(data)
std_dev = np.std(data)
print(mean)      <span class="hljs-comment"># Output: 13.2</span>
print(std_dev)    <span class="hljs-comment"># Output: 4.527692569068708</span>

<span class="hljs-comment"># Generate random numbers from a normal distribution</span>
random_data = np.random.normal(loc=mean, scale=std_dev, size=<span class="hljs-number">1000</span>)
</code></pre>
<p><strong>Example 3: Linear Algebra (Matrix Operations)</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Create a 2x3 matrix</span>
matrix = np.array([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>], [<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>]])

<span class="hljs-comment"># Matrix multiplication</span>
product = np.dot(matrix, matrix.T)  
print(product)
</code></pre>
<p><strong>Example 4: Image Processing</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> PIL <span class="hljs-keyword">import</span> Image
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Load an image</span>
image = Image.open(<span class="hljs-string">"my_image.jpg"</span>)  

<span class="hljs-comment"># Convert the image to a NumPy array</span>
image_array = np.array(image)

<span class="hljs-comment"># Access and modify pixel values</span>
red_channel = image_array[:, :, <span class="hljs-number">0</span>]  <span class="hljs-comment"># Extract the red channel</span>
image_array[:, :, <span class="hljs-number">1</span>] = <span class="hljs-number">0</span>            <span class="hljs-comment"># Set the green channel to zero</span>

<span class="hljs-comment"># Display the modified image</span>
modified_image = Image.fromarray(image_array)
modified_image.show()
</code></pre>
<p><strong>Explanation:</strong> In this example, we demonstrate how you can use NumPy arrays to represent and manipulate image data. We load an image, convert it to a NumPy array, extract a specific color channel (red), modify another channel (green), and then display the resulting image. This highlights the power of NumPy in image processing tasks.</p>
<p><strong>Example 5: Financial Analysis</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Stock prices over time</span>
prices = np.array([<span class="hljs-number">100</span>, <span class="hljs-number">105</span>, <span class="hljs-number">98</span>, <span class="hljs-number">112</span>, <span class="hljs-number">107</span>])

<span class="hljs-comment"># Calculate daily returns</span>
daily_returns = np.diff(prices) / prices[:<span class="hljs-number">-1</span>]
print(daily_returns)  <span class="hljs-comment"># Output: [0.05 -0.06734694 0.14285714 -0.04464286]</span>

<span class="hljs-comment"># Calculate cumulative returns</span>
cumulative_returns = np.cumprod(<span class="hljs-number">1</span> + daily_returns) - <span class="hljs-number">1</span>
print(cumulative_returns)  <span class="hljs-comment"># Output: [0.05 -0.01566265 0.12299465 0.07407407]</span>
</code></pre>
<p><strong>Explanation:</strong> Here, NumPy's <code>diff()</code> function efficiently calculates daily returns from stock prices. Then, <code>cumprod()</code> is used to compute cumulative returns, demonstrating NumPy's capabilities in financial analysis.</p>
<p><strong>Example 6: Scientific Simulations</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Simulate projectile motion</span>
t = np.linspace(<span class="hljs-number">0</span>, <span class="hljs-number">10</span>, <span class="hljs-number">100</span>)  <span class="hljs-comment"># Time points</span>
v0 = <span class="hljs-number">20</span>  <span class="hljs-comment"># Initial velocity</span>
theta = np.radians(<span class="hljs-number">45</span>)  <span class="hljs-comment"># Launch angle in radians</span>
g = <span class="hljs-number">9.81</span>  <span class="hljs-comment"># Acceleration due to gravity</span>

x = v0 * np.cos(theta) * t
y = v0 * np.sin(theta) * t - <span class="hljs-number">0.5</span> * g * t**<span class="hljs-number">2</span>

plt.plot(x, y)
plt.xlabel(<span class="hljs-string">'Distance (m)'</span>)
plt.ylabel(<span class="hljs-string">'Height (m)'</span>)
plt.title(<span class="hljs-string">'Projectile Motion'</span>)
plt.show()
</code></pre>
<p><strong>Explanation:</strong> In this example, we simulate the trajectory of a projectile using NumPy's trigonometric functions (<code>cos</code>, <code>sin</code>) and array operations. The resulting positions are plotted using Matplotlib, illustrating NumPy's role in scientific simulations.</p>
<p>These examples demonstrate just a glimpse of NumPy's capabilities. As you delve deeper into the library, you'll discover a vast array of functions and tools that can revolutionize your data analysis workflows.</p>
<h4 id="heading-222-mathematical-operations">2.2.2 Mathematical Operations</h4>
<p>Unlock the full potential of your numerical data with NumPy's extensive suite of mathematical operations. </p>
<p>If you're tired of writing cumbersome loops for basic calculations, NumPy's vectorized approach eliminates this need, enabling you to perform operations on entire arrays with a single, elegant command. This translates to faster, more efficient data processing, empowering you to focus on analysis and insights, not tedious code implementation.</p>
<p><strong>Element-wise Operations:</strong> NumPy allows you to apply arithmetic functions like addition, subtraction, multiplication, and division directly to arrays. These operations are performed element-wise, meaning that the corresponding elements in each array are combined.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

data = np.array([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
result = data * <span class="hljs-number">2</span>  <span class="hljs-comment"># Output: [2 4 6]</span>
</code></pre>
<p><strong>Universal Functions (ufuncs):</strong> NumPy offers a wide range of universal functions (<code>ufuncs</code>) that operate element-wise on arrays. These functions provide a concise way to perform common mathematical tasks like trigonometric calculations, exponentiation, logarithms, and more.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

angles = np.array([<span class="hljs-number">0</span>, np.pi/<span class="hljs-number">2</span>, np.pi])
sin_values = np.sin(angles)  <span class="hljs-comment"># Output: [0. 1. 0.]</span>
</code></pre>
<p><strong>Aggregation Functions:</strong> Need to summarize your data? NumPy's aggregation functions, such as <code>sum</code>, <code>mean</code>, <code>median</code>, <code>min</code>, and <code>max</code>, enable you to compute statistics across entire arrays or along specific axes.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

data = np.array([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>])
total = np.sum(data)        <span class="hljs-comment"># Output: 15</span>
average = np.mean(data)     <span class="hljs-comment"># Output: 3.0</span>
</code></pre>
<p><strong>Broadcasting:</strong> Broadcasting is a powerful feature that automatically expands the dimensions of arrays during arithmetic operations. This allows you to seamlessly perform calculations between arrays of different shapes, enhancing flexibility and simplifying code.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

data = np.array([<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>])
scalar = <span class="hljs-number">10</span>
result = data + scalar  <span class="hljs-comment"># Output: [11 12 13]</span>
</code></pre>
<p><strong>Linear Algebra Operations:</strong> For more advanced mathematical tasks, NumPy provides a comprehensive set of linear algebra functions. You can calculate dot products, solve linear equations, perform matrix operations, and more.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

A = np.array([[<span class="hljs-number">1</span>, <span class="hljs-number">2</span>], [<span class="hljs-number">3</span>, <span class="hljs-number">4</span>]])
B = np.array([[<span class="hljs-number">5</span>, <span class="hljs-number">6</span>], [<span class="hljs-number">7</span>, <span class="hljs-number">8</span>]])
C = np.matmul(A, B)  <span class="hljs-comment"># Matrix multiplication: C = A * B</span>
print(C)  <span class="hljs-comment"># Output: [[19 22] [43 50]]</span>
</code></pre>
<p><strong>Practical Advice:</strong></p>
<ul>
<li><strong>Leverage Vectorization:</strong> Whenever possible, avoid explicit Python loops and opt for NumPy's vectorized operations to drastically speed up your calculations.</li>
<li><strong>Explore the Documentation:</strong> NumPy's documentation is an invaluable resource. Familiarize yourself with its extensive range of mathematical functions to discover new ways to analyze and manipulate your data.</li>
<li><strong>Optimize Your Code:</strong> Use profiling tools to identify performance bottlenecks in your code and leverage NumPy's capabilities to optimize your calculations further.</li>
</ul>
<p>By mastering NumPy's mathematical operations, you'll transform your data analysis workflow into a well-oiled machine, capable of handling complex calculations with speed, precision, and efficiency.</p>
<h4 id="heading-223-random-number-generation">2.2.3 Random Number Generation</h4>
<p>In the world of data science and machine learning, the ability to generate random data is a superpower. It's your key to creating test datasets, simulating real-world scenarios, and exploring the fascinating realm of probability.  </p>
<p>NumPy's random module puts this power in your hands, providing a comprehensive suite of functions for generating random numbers with precision and control.</p>
<h5 id="heading-why-randomness-matters">Why Randomness Matters:</h5>
<p><strong>1. Testing and Validation:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-function"><span class="hljs-keyword">def</span> <span class="hljs-title">my_sorting_algorithm</span>(<span class="hljs-params">arr</span>):</span>
    <span class="hljs-comment"># (Your sorting algorithm implementation)</span>

<span class="hljs-comment"># Generate random data for testing</span>
test_data = np.random.randint(<span class="hljs-number">0</span>, <span class="hljs-number">100</span>, size=<span class="hljs-number">1000</span>)  <span class="hljs-comment"># 1000 random integers between 0 and 99</span>

<span class="hljs-comment"># Test your algorithm with various inputs</span>
is_sorted = all(test_data[i] &lt;= test_data[i+<span class="hljs-number">1</span>] <span class="hljs-keyword">for</span> i <span class="hljs-keyword">in</span> range(len(test_data) - <span class="hljs-number">1</span>))
<span class="hljs-keyword">if</span> is_sorted:
    print(<span class="hljs-string">"Sorting algorithm passed the test."</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"Sorting algorithm failed the test."</span>)
</code></pre>
<p>We first create an array (<code>test_data</code>) of random integers to simulate a variety of inputs. Then, we pass this array to our custom sorting algorithm (<code>my_sorting_algorithm</code>) and verify if the output is indeed sorted. </p>
<p>By using random data, we ensure our algorithm is tested with a wide range of possible inputs, increasing confidence in its correctness.</p>
<p><strong>2. Simulations:</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Simulate stock price movement (simplified example)</span>
initial_price = <span class="hljs-number">100</span>
daily_volatility = <span class="hljs-number">0.02</span>
days = <span class="hljs-number">365</span>
prices = [initial_price]
<span class="hljs-keyword">for</span> _ <span class="hljs-keyword">in</span> range(days):
    daily_change = np.random.normal(<span class="hljs-number">0</span>, daily_volatility)
    prices.append(prices[<span class="hljs-number">-1</span>] * (<span class="hljs-number">1</span> + daily_change))

<span class="hljs-comment"># Visualize the simulated stock prices</span>
plt.plot(prices)
plt.xlabel(<span class="hljs-string">'Days'</span>)
plt.ylabel(<span class="hljs-string">'Price'</span>)
plt.title(<span class="hljs-string">'Simulated Stock Prices'</span>)
plt.show()
</code></pre>
<p>In this example, we simulate the daily changes in a stock's price using <code>np.random.normal()</code>, which generates random values from a normal distribution with a specified mean (expected daily change) and standard deviation (volatility). This allows us to create a realistic model of how stock prices might fluctuate over time.</p>
<p><strong>3. Statistical Analysis (Bootstrapping):</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Original data</span>
data = np.array([<span class="hljs-number">12</span>, <span class="hljs-number">15</span>, <span class="hljs-number">18</span>, <span class="hljs-number">11</span>, <span class="hljs-number">14</span>])

<span class="hljs-comment"># Number of bootstrap samples</span>
num_samples = <span class="hljs-number">1000</span>

<span class="hljs-comment"># Create bootstrap samples</span>
bootstrap_samples = np.random.choice(data, size=(num_samples, len(data)), replace=<span class="hljs-literal">True</span>)

<span class="hljs-comment"># Calculate the mean for each bootstrap sample</span>
bootstrap_means = np.mean(bootstrap_samples, axis=<span class="hljs-number">1</span>)

<span class="hljs-comment"># Estimate the standard error of the mean</span>
standard_error = np.std(bootstrap_means)

print(<span class="hljs-string">"Standard Error of the Mean:"</span>, standard_error)
</code></pre>
<p>Bootstrapping is a resampling technique used to estimate the variability of a statistic (for example, the mean). We create multiple bootstrap samples by randomly sampling with replacement from the original data. We then calculate the statistic of interest (here, the mean) for each sample. </p>
<p>The standard deviation of these bootstrap means provides an estimate of the standard error of the original mean, helping us assess its reliability.</p>
<h5 id="heading-numpys-random-arsenal">NumPy's Random Arsenal:</h5>
<p>NumPy offers a wide array of functions for generating random numbers from different probability distributions. Some of the most commonly used distributions include:</p>
<ul>
<li><strong>Uniform Distribution:</strong> Generates random numbers with equal probability within a specified range.</li>
<li><strong>Normal (Gaussian) Distribution:</strong>  Models phenomena that tend to cluster around a central value, such as heights, weights, or test scores.</li>
<li><strong>Binomial Distribution:</strong> Describes the probability of a certain number of successes in a sequence of independent trials, like flipping a coin.</li>
<li><strong>Poisson Distribution:</strong>  Models the probability of a given number of events occurring in a fixed interval of time or space.</li>
</ul>
<p>Practical Examples:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Generate a random integer between 0 and 9</span>
random_integer = np.random.randint(<span class="hljs-number">10</span>)

<span class="hljs-comment"># Generate an array of 5 random floats between 0 and 1</span>
random_floats = np.random.rand(<span class="hljs-number">5</span>)

<span class="hljs-comment"># Generate 1000 samples from a normal distribution</span>
samples = np.random.normal(loc=<span class="hljs-number">0</span>, scale=<span class="hljs-number">1</span>, size=<span class="hljs-number">1000</span>)
</code></pre>
<p><strong>Tips for Effective Random Number Generation:</strong></p>
<ul>
<li><strong>Seed for Reproducibility:</strong>  Set a random seed using <code>np.random.seed()</code> to ensure that your random number sequences can be reproduced later, making your experiments and simulations more reliable.</li>
<li><strong>Choose the Right Distribution:</strong> Select the probability distribution that best matches the characteristics of the data you want to simulate.</li>
<li><strong>Experiment and Explore:</strong> Don't be afraid to experiment with different distributions and parameters to find the ones that best suit your needs.</li>
</ul>
<p>Embrace the power of randomness with NumPy's random module. Unleash your creativity, test your models rigorously, and simulate complex scenarios with confidence. By incorporating randomness into your data analysis toolkit, you'll gain a deeper understanding of probability, risk, and uncertainty, empowering you to make more informed decisions in an unpredictable world.</p>
<h3 id="heading-23-matplotlib">2.3 Matplotlib</h3>
<p>In the world of data, visuals are your key to unlocking deeper understanding and clear communication. Matplotlib is a versatile tool that helps you create a wide range of graphs and charts, making your data easier to interpret and share. It's your friendly guide to bringing numbers to life.</p>
<h4 id="heading-with-matplotlib-you-can-create">With Matplotlib, you can create:</h4>
<ul>
<li>Line charts to track trends over time</li>
<li>Scatter plots to explore relationships between different factors</li>
<li>Bar charts to compare categories</li>
<li>Histograms to see how data is distributed</li>
<li>Pie charts to show proportions</li>
<li>And many more!</li>
</ul>
<p>Matplotlib gives you control over the look and feel of your visuals. You can easily customize colors, labels, and styles to make your charts informative and visually appealing. This is your chance to create clear, impactful visuals that communicate your findings effectively.</p>
<p>In this section, we'll dive into Matplotlib and learn how to create different types of charts. We'll also explore customization options, so you can create visuals that perfectly suit your needs. Let's start transforming your data into eye-catching insights.</p>
<h4 id="heading-231-basic-plots">2.3.1 Basic Plots</h4>
<blockquote>
<p>"The simple graph has brought more information to the data analyst's mind than any other device." – John Tukey, Statistician</p>
</blockquote>
<p>Visuals aren't just pretty pictures – they're the key to unlocking your data's potential. Matplotlib's basic plot types empower you to tell compelling stories, reveal hidden patterns, and communicate complex insights with clarity.</p>
<h5 id="heading-line-charts-unveiling-trends-over-time">Line Charts: Unveiling Trends Over Time</h5>
<p>Line charts are your go-to tool for visualizing trends and changes over time. Whether you're tracking sales figures, stock prices, or temperature fluctuations, line charts paint a clear picture of how your data evolves.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Sample data</span>
x = np.arange(<span class="hljs-number">1</span>, <span class="hljs-number">11</span>)
y = np.array([<span class="hljs-number">2</span>, <span class="hljs-number">4</span>, <span class="hljs-number">1</span>, <span class="hljs-number">7</span>, <span class="hljs-number">3</span>, <span class="hljs-number">6</span>, <span class="hljs-number">5</span>, <span class="hljs-number">9</span>, <span class="hljs-number">8</span>, <span class="hljs-number">10</span>])

plt.figure(figsize=(<span class="hljs-number">8</span>, <span class="hljs-number">6</span>))  <span class="hljs-comment"># Optional: set figure size</span>
plt.plot(x, y, marker=<span class="hljs-string">'o'</span>)  <span class="hljs-comment"># Plot line with circular markers</span>
plt.xlabel(<span class="hljs-string">'Time'</span>)
plt.ylabel(<span class="hljs-string">'Value'</span>)
plt.title(<span class="hljs-string">'Line Chart Example'</span>)
plt.grid(axis=<span class="hljs-string">'y'</span>)  <span class="hljs-comment"># Optional: add gridlines</span>
plt.show()
</code></pre>
<p>In the above code, we:</p>
<ol>
<li>Import the necessary libraries.</li>
<li>Define some sample data for x and y.</li>
<li>Set the figure size (optional).</li>
<li>Plot the line chart using plt.plot, which takes the x and y coordinates as input. You can customize it by adding labels to the x and y axis with <code>plt.xlabel</code> and <code>plt.ylabel</code> and give it a title with <code>plt.title</code>.</li>
<li>Finally, it is displayed with <code>plt.show()</code></li>
</ol>
<h5 id="heading-scatter-plots-revealing-relationships">Scatter Plots: Revealing Relationships</h5>
<p>Scatter plots are your window into the world of relationships between variables. They showcase the distribution of data points, helping you identify correlations, clusters, and outliers.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sample data</span>
x = np.random.rand(<span class="hljs-number">50</span>)  <span class="hljs-comment"># 50 random values between 0 and 1</span>
y = np.random.rand(<span class="hljs-number">50</span>)

plt.figure(figsize=(<span class="hljs-number">8</span>, <span class="hljs-number">6</span>))
plt.scatter(x, y, marker=<span class="hljs-string">'x'</span>, color=<span class="hljs-string">'red'</span>)  <span class="hljs-comment"># Plot scatter with 'x' markers</span>
plt.xlabel(<span class="hljs-string">'X Values'</span>)
plt.ylabel(<span class="hljs-string">'Y Values'</span>)
plt.title(<span class="hljs-string">'Scatter Plot Example'</span>)
plt.grid(<span class="hljs-literal">True</span>) 
plt.show()
</code></pre>
<p>In the code above, we:</p>
<ol>
<li>Import the necessary libraries.</li>
<li>Create arrays x and y with 50 random values between 0 and 1 using np.random.rand(50).</li>
<li>Set the figure size.</li>
<li>Create a scatter plot using plt.scatter with x and y coordinates and marker.</li>
<li>Set x and y axis labels and set the plot title.</li>
<li>Display the plot with <code>plt.show()</code></li>
</ol>
<h5 id="heading-bar-charts-comparing-quantities-across-categories">Bar Charts: Comparing Quantities Across Categories</h5>
<p>Bar charts are perfect for visualizing comparisons between categorical data. They make it easy to see which categories are the highest or lowest, or how values differ across groups.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sample data</span>
categories = [<span class="hljs-string">'A'</span>, <span class="hljs-string">'B'</span>, <span class="hljs-string">'C'</span>, <span class="hljs-string">'D'</span>]
values = [<span class="hljs-number">25</span>, <span class="hljs-number">40</span>, <span class="hljs-number">32</span>, <span class="hljs-number">18</span>]

plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>))
plt.bar(categories, values, color=<span class="hljs-string">'skyblue'</span>)  <span class="hljs-comment"># Plot bar chart</span>
plt.xlabel(<span class="hljs-string">'Categories'</span>)
plt.ylabel(<span class="hljs-string">'Values'</span>)
plt.title(<span class="hljs-string">'Bar Chart Example'</span>)
plt.show()
</code></pre>
<h5 id="heading-histograms-unveiling-data-distribution">Histograms: Unveiling Data Distribution</h5>
<p>Histograms provide a visual representation of a dataset's distribution. They reveal how frequently different values occur, helping you identify central tendencies, spread, and potential skewness in your data.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sample data</span>
data = np.random.normal(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1000</span>)  <span class="hljs-comment"># 1000 samples from a standard normal distribution</span>

plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>))
plt.hist(data, bins=<span class="hljs-number">20</span>, color=<span class="hljs-string">'lightgreen'</span>, alpha=<span class="hljs-number">0.7</span>) <span class="hljs-comment"># Plot histogram</span>
plt.xlabel(<span class="hljs-string">'Values'</span>)
plt.ylabel(<span class="hljs-string">'Frequency'</span>)
plt.title(<span class="hljs-string">'Histogram Example'</span>)
plt.show()
</code></pre>
<p>In the code above, we:</p>
<ol>
<li>Import the necessary libraries.</li>
<li>Generate 1000 random values from a standard normal distribution with a mean of 0 and standard deviation of 1.</li>
<li>Set the figure size</li>
<li>Plot a histogram using plt.hist with data, bins, color, and alpha values.</li>
<li>Give x and y axis labels and set the plot title.</li>
<li>Display the plot using plt.show()</li>
</ol>
<h4 id="heading-232-customization">2.3.2 Customization</h4>
<p>Your data visualizations are more than just graphs and charts – they're a form of visual communication that can captivate, inform, and inspire action. </p>
<p>Matplotlib's extensive customization options empower you to craft visuals that not only showcase your data but also tell a compelling story.</p>
<h5 id="heading-colors-evoking-emotion-and-enhancing-clarity">Colors: Evoking Emotion and Enhancing Clarity</h5>
<p>Colors are not merely aesthetic choices. They also hold the power to evoke emotions and guide the viewer's attention. Research suggests that color can enhance memory and comprehension by up to 78%. By strategically using colors, you can:</p>
<ul>
<li><strong>Highlight Key Insights:</strong> Draw the eye to crucial data points or trends.</li>
<li><strong>Create Visual Hierarchy:</strong> Guide the viewer through the narrative of your plot.</li>
<li><strong>Differentiate Categories:</strong> Distinguish between groups of data effectively.</li>
</ul>
<pre><code class="lang-python">plt.bar(categories, values, color=[<span class="hljs-string">'skyblue'</span>, <span class="hljs-string">'lightcoral'</span>, <span class="hljs-string">'gold'</span>])
</code></pre>
<p><strong>Explanation:</strong> The code above creates a bar chart and sets three colors for the bars which can represent categories.</p>
<h5 id="heading-labels-and-titles-guiding-the-viewer">Labels and Titles: Guiding the Viewer</h5>
<p>Clear and informative labels and titles are essential for guiding your audience through your visualizations. They provide context and ensure that the message of your plot is easily understood.</p>
<pre><code class="lang-python">plt.xlabel(<span class="hljs-string">'Year'</span>)
plt.ylabel(<span class="hljs-string">'Sales Revenue (Millions)'</span>)
plt.title(<span class="hljs-string">'Annual Sales Revenue 2018-2023'</span>)
</code></pre>
<p><strong>Explanation:</strong> The code above sets labels for the x and y axis along with a title.</p>
<h5 id="heading-styles-and-themes-setting-the-mood">Styles and Themes: Setting the Mood</h5>
<p>Matplotlib offers various plot styles and themes that you can apply to change the overall look and feel of your visualizations. These styles can range from simple, clean designs to more elaborate and visually engaging options.</p>
<pre><code class="lang-python">plt.style.use(<span class="hljs-string">'seaborn-v0_8-darkgrid'</span>)  <span class="hljs-comment"># Apply a Seaborn style</span>
</code></pre>
<h5 id="heading-beyond-the-basics-advanced-customization">Beyond the Basics: Advanced Customization</h5>
<p>As you become more comfortable with Matplotlib, you can explore more advanced customization techniques, such as:</p>
<ul>
<li><strong>Annotations and Text:</strong> Add text directly to your plots for emphasis or explanation.</li>
<li><strong>Legends:</strong> Clearly identify different data series or categories.</li>
<li><strong>Gridlines and Axes:</strong> Control the appearance of gridlines and axes to enhance readability.</li>
<li><strong>Subplots:</strong> Create multiple plots within a single figure.</li>
</ul>
<p>Matplotlib empowers you to create visually stunning and informative plots that tell a compelling story. By mastering its customization capabilities, you'll transform your data visualizations into powerful communication tools that drive understanding and action.</p>
<h2 id="heading-3-practical-examples-from-theory-to-action">3. Practical Examples: From Theory to Action</h2>
<p>Data analysis is about more than just abstract concepts. It's also about applying your knowledge to solve real problems. In this chapter, you'll bridge the gap between theory and practice, gaining hands-on experience with the tools and techniques you've learned so far.</p>
<p>By working with concrete examples, you'll solidify your understanding of Python, Pandas, and Matplotlib, and you'll build the confidence to tackle real-world data challenges.</p>
<p>What you'll learn in this chapter:</p>
<p><strong>Loading and Cleaning Data:</strong></p>
<ul>
<li>Import data from CSV files, the most common format for storing structured data.</li>
<li>Handle missing values—a common issue that can skew your analysis—using Pandas' powerful imputation techniques.</li>
<li>Standardize data types to ensure consistency and accuracy in your calculations.</li>
</ul>
<p><strong>Exploring Data with Pandas:</strong></p>
<ul>
<li>Leverage essential Pandas functions like <code>.describe()</code>, <code>.groupby()</code>, and <code>.value_counts()</code> to uncover hidden patterns and insights within your data.</li>
<li>Gain a deeper understanding of your data's characteristics and relationships.</li>
</ul>
<p><strong>Visualizing Trends with Matplotlib:</strong></p>
<ul>
<li>Craft informative and visually appealing plots to reveal trends, correlations, and distributions within your data.</li>
<li>Use line charts, scatter plots, and other visualization techniques to communicate your findings effectively.</li>
</ul>
<p>Are you ready to put theory into practice and witness the transformative power of data analysis? Let's dive in and discover how Python, Pandas, and Matplotlib can empower you to extract actionable insights from real-world data.</p>
<p>In this series of examples, we will make use of the following example CSV file. </p>
<pre><code>Order ID,Order <span class="hljs-built_in">Date</span>,Customer ID,Segment,Product,Category,Sales,Quantity,Profit
<span class="hljs-number">1001</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-01</span>,CUST<span class="hljs-number">-101</span>,Consumer,Product A,Office Supplies,<span class="hljs-number">27.90</span>,<span class="hljs-number">2</span>,<span class="hljs-number">10.34</span>
<span class="hljs-number">1002</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-02</span>,CUST<span class="hljs-number">-102</span>,Corporate,Product B,Technology,<span class="hljs-number">1024.99</span>,<span class="hljs-number">1</span>,<span class="hljs-number">512.49</span>
<span class="hljs-number">1003</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-03</span>,CUST<span class="hljs-number">-103</span>,Home Office,Product C,Furniture,<span class="hljs-number">436.50</span>,<span class="hljs-number">3</span>,<span class="hljs-number">-109.12</span>
<span class="hljs-number">1004</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-04</span>,CUST<span class="hljs-number">-101</span>,Consumer,Product D,Office Supplies,<span class="hljs-number">15.99</span>,<span class="hljs-number">5</span>,<span class="hljs-number">6.39</span>
<span class="hljs-number">1005</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-05</span>,CUST<span class="hljs-number">-104</span>,Consumer,Product E,Technology,<span class="hljs-number">799.99</span>,<span class="hljs-number">1</span>,<span class="hljs-number">239.99</span>
<span class="hljs-number">1006</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-06</span>,CUST<span class="hljs-number">-105</span>,Corporate,Product F,Furniture,<span class="hljs-number">214.70</span>,<span class="hljs-number">2</span>,<span class="hljs-number">-32.20</span>
<span class="hljs-number">1007</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-07</span>,CUST<span class="hljs-number">-106</span>,Home Office,Product G,Office Supplies,<span class="hljs-number">9.99</span>,<span class="hljs-number">3</span>,<span class="hljs-number">2.99</span>
<span class="hljs-number">1008</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-08</span>,CUST<span class="hljs-number">-107</span>,Corporate,Product H,Technology,<span class="hljs-number">549.95</span>,<span class="hljs-number">2</span>,<span class="hljs-number">164.98</span>
<span class="hljs-number">1009</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-09</span>,CUST<span class="hljs-number">-108</span>,Consumer,Product A,Office Supplies,<span class="hljs-number">27.90</span>,<span class="hljs-number">4</span>,<span class="hljs-number">20.68</span>
<span class="hljs-number">1010</span>,<span class="hljs-number">2023</span><span class="hljs-number">-01</span><span class="hljs-number">-10</span>,CUST<span class="hljs-number">-109</span>,Home Office,Product I,Furniture,<span class="hljs-number">120.00</span>,<span class="hljs-number">1</span>,<span class="hljs-number">60.00</span>
</code></pre><h3 id="heading-31-loading-and-cleaning-data">3.1 Loading and Cleaning Data</h3>
<p>Real-world data is rarely pristine. It often arrives in messy CSV files, riddled with missing values, inconsistent formats, and other imperfections that can derail your analysis. </p>
<p>But fear not – Pandas is your trusty sidekick in this data wrangling adventure. Let's walk through the essential steps of importing and cleaning data using Pandas and our sample CSV file, <code>sales_data.csv</code>.</p>
<h4 id="heading-step-1-import-your-data">Step 1: Import Your Data</h4>
<p>First, make sure you have the <code>sales_data.csv</code> file in your working directory (or provide the correct file path). Then, use Pandas' <code>read_csv</code> function to import it into a DataFrame:</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

df = pd.read_csv(<span class="hljs-string">'sales_data.csv'</span>)
print(df.head())  <span class="hljs-comment"># Display the first 5 rows for a quick overview</span>
</code></pre>
<p>This will load the CSV file into a Pandas DataFrame, a versatile table-like structure that allows for easy manipulation and analysis.</p>
<h4 id="heading-step-2-assess-your-data">Step 2: Assess Your Data</h4>
<p>Before you dive into cleaning, take a moment to assess your data. What does it look like? Are there any obvious issues? Pandas provides several functions to help you get a feel for your dataset:</p>
<pre><code class="lang-python">print(df.info())  <span class="hljs-comment"># Get information about columns, data types, and missing values</span>
print(df.describe())  <span class="hljs-comment"># Get summary statistics for numerical columns</span>
</code></pre>
<h4 id="heading-step-3-handle-missing-values">Step 3: Handle Missing Values</h4>
<p>Missing values are a common problem in real-world data. Pandas offers a variety of ways to handle them:</p>
<ul>
<li><strong>Dropping Rows:</strong> If missing values are sparse and unlikely to significantly impact your analysis, you can simply drop the rows containing them.</li>
</ul>
<pre><code class="lang-python">df.dropna(inplace=<span class="hljs-literal">True</span>)
</code></pre>
<ul>
<li><strong>Filling with a Value:</strong> You can fill missing values with a specific value, such as 0 or the mean of the column.</li>
</ul>
<pre><code class="lang-python">df[<span class="hljs-string">'Sales'</span>].fillna(df[<span class="hljs-string">'Sales'</span>].mean(), inplace=<span class="hljs-literal">True</span>)
</code></pre>
<ul>
<li><strong>Forward or Backward Fill:</strong> For time series data, you can fill missing values with the previous or next valid value.</li>
</ul>
<pre><code class="lang-python">df[<span class="hljs-string">'Sales'</span>].fillna(method=<span class="hljs-string">'ffill'</span>, inplace=<span class="hljs-literal">True</span>)  <span class="hljs-comment"># Forward fill</span>
</code></pre>
<ul>
<li><strong>Interpolation:</strong> Estimate missing values based on a pattern in the data (for example, linear interpolation).</li>
</ul>
<pre><code class="lang-python">df[<span class="hljs-string">'Sales'</span>].interpolate(method=<span class="hljs-string">'linear'</span>, inplace=<span class="hljs-literal">True</span>)
</code></pre>
<h4 id="heading-step-4-standardize-data-types">Step 4: Standardize Data Types</h4>
<p>Ensure consistency in your data by converting columns to the appropriate data types. For example:</p>
<pre><code class="lang-python">df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>])  <span class="hljs-comment"># Convert to datetime</span>
df[<span class="hljs-string">'Sales'</span>] = pd.to_numeric(df[<span class="hljs-string">'Sales'</span>])          <span class="hljs-comment"># Convert to numeric</span>
</code></pre>
<h4 id="heading-step-5-deal-with-outliers-optional">Step 5: Deal with Outliers (Optional)</h4>
<p>Outliers are extreme values that can distort your analysis. Depending on your data and goals, you might choose to:</p>
<ul>
<li><strong>Remove outliers:</strong> This can be done based on statistical thresholds (for example, z-scores or interquartile range).</li>
<li><strong>Cap outliers:</strong> Replace extreme values with a more reasonable limit.</li>
<li><strong>Transform the data:</strong> Apply a transformation (for example, logarithmic) to reduce the impact of outliers.</li>
<li><strong>Keep outliers:</strong>  If they're valid data points, outliers might offer valuable insights.</li>
</ul>
<h5 id="heading-example-removing-outliers-using-z-scores">Example: Removing Outliers using Z-scores:</h5>
<pre><code class="lang-python"><span class="hljs-keyword">from</span> scipy <span class="hljs-keyword">import</span> stats

z = np.abs(stats.zscore(df[<span class="hljs-string">'Sales'</span>]))
df = df[(z &lt; <span class="hljs-number">3</span>)]  <span class="hljs-comment"># Keep only rows with z-score less than 3</span>
</code></pre>
<p>By following these steps, you'll be well on your way to transforming raw, messy data into a clean and structured dataset ready for your insightful analysis.</p>
<p>Remember, data cleaning is an iterative process, and there's no one-size-fits-all solution. Experiment with different techniques to find the best approach for your specific data.</p>
<h5 id="heading-full-code">Full Code:</h5>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">from</span> scipy <span class="hljs-keyword">import</span> stats
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

df = pd.read_csv(<span class="hljs-string">'sales_data.csv'</span>)

print(<span class="hljs-string">"Data Preview:"</span>)
print(df.head().to_markdown(index=<span class="hljs-literal">False</span>, numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

print(<span class="hljs-string">"\nData Information:"</span>)
print(df.info())

print(<span class="hljs-string">"\nSummary Statistics of Numeric Columns:"</span>)
print(df.describe().to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

df.dropna(inplace=<span class="hljs-literal">True</span>)  
df[<span class="hljs-string">'Sales'</span>].fillna(df[<span class="hljs-string">'Sales'</span>].mean(), inplace=<span class="hljs-literal">True</span>) 
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>])  
df[<span class="hljs-string">'Sales'</span>] = pd.to_numeric(df[<span class="hljs-string">'Sales'</span>])          

z = np.abs(stats.zscore(df[<span class="hljs-string">'Sales'</span>]))
df = df[(z &lt; <span class="hljs-number">3</span>)]  

print(<span class="hljs-string">"\nData After Cleaning and Outlier Removal:"</span>)
print(df.head().to_markdown(index=<span class="hljs-literal">False</span>, numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

<span class="hljs-comment"># Group data by category and calculate total sales</span>
total_sales_by_category = df.groupby(<span class="hljs-string">'Category'</span>)[<span class="hljs-string">'Sales'</span>].sum()

<span class="hljs-comment"># Display the result</span>
print(<span class="hljs-string">"\nTotal Sales by Category:"</span>)
print(total_sales_by_category.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))
</code></pre>
<h3 id="heading-32-exploring-data-with-pandas">3.2 Exploring Data with Pandas</h3>
<p>With your data loaded and cleaned, it's time to embark on the exciting journey of data exploration. Pandas equips you with a powerful suite of functions to analyze your dataset, uncover hidden patterns, and gain actionable insights.</p>
<h4 id="heading-dfdescribe-quantitative-snapshot"><code>df.describe()</code> – Quantitative Snapshot</h4>
<p>This function provides a concise statistical summary of your numerical columns. It's your initial reconnaissance mission, revealing central tendencies (mean, median), dispersion (standard deviation, range), and distribution quartiles. </p>
<p>This high-level overview quickly reveals potential outliers and distributions that warrant further investigation.</p>
<pre><code class="lang-python">print(df.describe().to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))
</code></pre>
<h4 id="heading-dfgroupby-segmenting-for-deeper-insights"><code>df.groupby()</code> – Segmenting for Deeper Insights</h4>
<p>Grouping is a fundamental technique in data analysis. Pandas' <code>groupby()</code> function allows you to segment your data based on categorical variables. </p>
<p>For instance, you can group your sales data by customer segment or product category to understand how these factors influence sales performance.</p>
<pre><code class="lang-python">sales_by_segment = df.groupby(<span class="hljs-string">'Segment'</span>)[<span class="hljs-string">'Sales'</span>].sum()
print(sales_by_segment.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))
</code></pre>
<h4 id="heading-dfvaluecounts-distribution-analysis"><code>df.value_counts()</code> –  Distribution Analysis</h4>
<p>Understanding the frequency distribution of categorical variables is crucial for identifying common patterns and potential anomalies. <code>.value_counts()</code> reveals how often each unique value appears in a column, giving you a snapshot of the distribution.</p>
<pre><code class="lang-python">product_popularity = df[<span class="hljs-string">'Product'</span>].value_counts()
print(product_popularity.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))
</code></pre>
<h4 id="heading-beyond-the-basics">Beyond the Basics</h4>
<p>These essential functions are just the tip of the iceberg. Pandas offers a multitude of other tools to explore your data. For instance, you can use the <code>df.corr()</code> method to calculate correlations between numerical columns, revealing potential relationships.</p>
<pre><code class="lang-python">sales_profit_correlation = df[<span class="hljs-string">'Sales'</span>].corr(df[<span class="hljs-string">'Profit'</span>])
print(<span class="hljs-string">"Correlation between Sales and Profit:"</span>, sales_profit_correlation)
</code></pre>
<p>Remember, data exploration is an iterative process. Start with these basic functions to gain a broad understanding of your data, then refine your analysis with more targeted questions and techniques. The insights you uncover will guide you towards making informed decisions and maximizing the value of your data.</p>
<p>Beyond the basics, Pandas offers a wealth of advanced tools for exploratory data analysis (EDA), allowing you to dig deeper into your data and uncover nuanced patterns, correlations, and trends that can inform your business strategies. Let's dive into some more sophisticated techniques using our <code>sales_data.csv</code> example.</p>
<h5 id="heading-segment-performance-deep-dive">Segment Performance Deep Dive:</h5>
<p>We've already seen how <code>groupby</code> can summarize total sales by segment. But let's take it a step further:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Calculate total sales, quantity, and profit by segment</span>
segment_summary = df.groupby(<span class="hljs-string">"Segment"</span>)[[<span class="hljs-string">"Sales"</span>, <span class="hljs-string">"Quantity"</span>, <span class="hljs-string">"Profit"</span>]].sum()

print(<span class="hljs-string">"\nSales, Quantity, and Profit Summary by Segment:"</span>)
print(segment_summary.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

<span class="hljs-comment"># Calculate average profit margin per sale by segment</span>
segment_summary[<span class="hljs-string">"Profit_Margin"</span>] = segment_summary[<span class="hljs-string">"Profit"</span>] / segment_summary[<span class="hljs-string">"Sales"</span>]
print(<span class="hljs-string">"\nAverage Profit Margin by Segment:"</span>)
print(segment_summary[[<span class="hljs-string">"Profit_Margin"</span>]].to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>, floatfmt=<span class="hljs-string">".2%"</span>))
</code></pre>
<p>This expanded analysis reveals not only total sales but also quantity and profit for each segment. We even calculate the average profit margin, uncovering which segment yields the most profit per sale.</p>
<h5 id="heading-uncover-customer-buying-patterns">Uncover Customer Buying Patterns:</h5>
<p>Let's delve into individual customer behavior to identify potential high-value customers or patterns in purchasing frequency.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Identify customers who have made more than one purchase</span>
repeat_customers = df[<span class="hljs-string">'Customer ID'</span>].value_counts()[df[<span class="hljs-string">'Customer ID'</span>].value_counts() &gt; <span class="hljs-number">1</span>]
print(<span class="hljs-string">"\nRepeat Customers:"</span>)
print(repeat_customers.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

<span class="hljs-comment"># Analyze the time between purchases for repeat customers</span>
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> timedelta
df[<span class="hljs-string">'Days_Since_Last_Purchase'</span>] = df.sort_values(<span class="hljs-string">'Order Date'</span>).groupby(<span class="hljs-string">'Customer ID'</span>)[<span class="hljs-string">'Order Date'</span>].diff()
repeat_customer_purchase_frequency = df[df[<span class="hljs-string">'Customer ID'</span>].isin(repeat_customers.index)][<span class="hljs-string">'Days_Since_Last_Purchase'</span>].describe()
print(<span class="hljs-string">"\nRepeat Customer Purchase Frequency (Days):"</span>)
print(repeat_customer_purchase_frequency.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))
</code></pre>
<p>We identify repeat customers and then analyze how frequently they make purchases. By understanding the typical time between purchases, you can tailor marketing strategies or loyalty programs to encourage repeat business.</p>
<p><strong>Practical Advice:</strong></p>
<ul>
<li><strong>Go Beyond the Obvious:</strong> Don't stop at basic summaries. Use Pandas' flexibility to dig deeper into your data.</li>
<li><strong>Think Strategically:</strong> How can you use the insights you uncover to drive action and improve business outcomes?</li>
<li><strong>Iterate and Refine:</strong> Data exploration is an ongoing process. As you learn more, refine your questions and explore new avenues of analysis.</li>
<li><strong>Don't be afraid to experiment:</strong> Pandas is a powerful tool. Try out different functions and combinations to see what reveals the most interesting patterns.</li>
</ul>
<p>By mastering these advanced EDA techniques with Pandas, you'll gain the ability to extract deeper insights from your data, making you an invaluable asset to your organization.</p>
<h5 id="heading-full-code-1">Full Code:</h5>
<pre><code class="lang-python">print(df.describe().to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

sales_by_segment = df.groupby(<span class="hljs-string">'Segment'</span>)[<span class="hljs-string">'Sales'</span>].sum()
print(sales_by_segment.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

product_popularity = df[<span class="hljs-string">'Product'</span>].value_counts()
print(product_popularity.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

sales_profit_correlation = df[<span class="hljs-string">'Sales'</span>].corr(df[<span class="hljs-string">'Profit'</span>])
print(<span class="hljs-string">"Correlation between Sales and Profit:"</span>, sales_profit_correlation)

<span class="hljs-comment"># Calculate total sales, quantity, and profit by segment</span>
segment_summary = df.groupby(<span class="hljs-string">"Segment"</span>)[[<span class="hljs-string">"Sales"</span>, <span class="hljs-string">"Quantity"</span>, <span class="hljs-string">"Profit"</span>]].sum()

print(<span class="hljs-string">"\nSales, Quantity, and Profit Summary by Segment:"</span>)
print(segment_summary.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

<span class="hljs-comment"># Calculate average profit margin per sale by segment</span>
segment_summary[<span class="hljs-string">"Profit_Margin"</span>] = segment_summary[<span class="hljs-string">"Profit"</span>] / segment_summary[<span class="hljs-string">"Sales"</span>]
print(<span class="hljs-string">"\nAverage Profit Margin by Segment:"</span>)
print(segment_summary[[<span class="hljs-string">"Profit_Margin"</span>]].to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>, floatfmt=<span class="hljs-string">".2%"</span>))

<span class="hljs-comment"># Identify customers who have made more than one purchase</span>
repeat_customers = df[<span class="hljs-string">'Customer ID'</span>].value_counts()[df[<span class="hljs-string">'Customer ID'</span>].value_counts() &gt; <span class="hljs-number">1</span>]
print(<span class="hljs-string">"\nRepeat Customers:"</span>)
print(repeat_customers.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))

<span class="hljs-comment"># Analyze the time between purchases for repeat customers</span>
<span class="hljs-keyword">from</span> datetime <span class="hljs-keyword">import</span> timedelta
df[<span class="hljs-string">'Days_Since_Last_Purchase'</span>] = df.sort_values(<span class="hljs-string">'Order Date'</span>).groupby(<span class="hljs-string">'Customer ID'</span>)[<span class="hljs-string">'Order Date'</span>].diff()
repeat_customer_purchase_frequency = df[df[<span class="hljs-string">'Customer ID'</span>].isin(repeat_customers.index)][<span class="hljs-string">'Days_Since_Last_Purchase'</span>].describe()
print(<span class="hljs-string">"\nRepeat Customer Purchase Frequency (Days):"</span>)
print(repeat_customer_purchase_frequency.to_markdown(numalign=<span class="hljs-string">"left"</span>, stralign=<span class="hljs-string">"left"</span>))
</code></pre>
<h3 id="heading-33-visualizing-trends-with-matplotlib">3.3 Visualizing Trends with Matplotlib</h3>
<p><strong>1. Total Sales Over Time (Line Chart):</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Convert 'Order Date' to datetime for proper plotting</span>
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>])

<span class="hljs-comment"># Group sales by order date and sum them up</span>
daily_sales = df.groupby(<span class="hljs-string">'Order Date'</span>)[<span class="hljs-string">'Sales'</span>].sum()

plt.figure(figsize=(<span class="hljs-number">12</span>, <span class="hljs-number">6</span>))
plt.plot(daily_sales, marker=<span class="hljs-string">'o'</span>)  <span class="hljs-comment"># Plot line chart with markers for data points</span>
plt.title(<span class="hljs-string">'Total Sales Over Time'</span>)
plt.xlabel(<span class="hljs-string">'Order Date'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.xticks(rotation=<span class="hljs-number">45</span>) 
plt.grid(axis=<span class="hljs-string">'y'</span>)
plt.show()
</code></pre>
<p>This line chart illustrates how your total sales have fluctuated over time, revealing trends, peaks, and valleys. It can help you identify seasonal patterns, the impact of marketing campaigns, or other factors influencing sales performance.</p>
<p><strong>2. Sales vs. Profit by Segment (Scatter Plot):</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Create a scatter plot for each segment</span>
segments = df[<span class="hljs-string">'Segment'</span>].unique()
colors = [<span class="hljs-string">'blue'</span>, <span class="hljs-string">'green'</span>, <span class="hljs-string">'orange'</span>]  <span class="hljs-comment"># Choose distinct colors for each segment</span>

plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>))
<span class="hljs-keyword">for</span> i, segment <span class="hljs-keyword">in</span> enumerate(segments):
    segment_data = df[df[<span class="hljs-string">'Segment'</span>] == segment]
    plt.scatter(segment_data[<span class="hljs-string">'Sales'</span>], segment_data[<span class="hljs-string">'Profit'</span>], c=colors[i], label=segment)

plt.title(<span class="hljs-string">'Sales vs. Profit by Segment'</span>)
plt.xlabel(<span class="hljs-string">'Sales'</span>)
plt.ylabel(<span class="hljs-string">'Profit'</span>)
plt.legend()
plt.show()
</code></pre>
<p>This scatter plot visualizes the relationship between sales and profit for each customer segment (Consumer, Corporate, Home Office). It helps you identify which segments are most profitable and whether there are any correlations between sales volume and profitability.</p>
<p><strong>3. Distribution of Sales by Category (Bar Chart):</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Calculate total sales by category</span>
sales_by_category = df.groupby(<span class="hljs-string">'Category'</span>)[<span class="hljs-string">'Sales'</span>].sum()

plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>))
plt.bar(sales_by_category.index, sales_by_category.values, color=<span class="hljs-string">'skyblue'</span>)
plt.title(<span class="hljs-string">'Total Sales by Category'</span>)
plt.xlabel(<span class="hljs-string">'Category'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.xticks(rotation=<span class="hljs-number">45</span>)
plt.show()
</code></pre>
<p>This bar chart provides a clear comparison of total sales across different product categories, highlighting which categories are driving your revenue.</p>
<p><strong>4. Distribution of Order Quantities (Histogram):</strong></p>
<pre><code class="lang-python">plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>))
plt.hist(df[<span class="hljs-string">'Quantity'</span>], bins=<span class="hljs-number">5</span>, color=<span class="hljs-string">'salmon'</span>, alpha=<span class="hljs-number">0.7</span>, rwidth=<span class="hljs-number">0.8</span>)
plt.title(<span class="hljs-string">'Distribution of Order Quantities'</span>)
plt.xlabel(<span class="hljs-string">'Quantity'</span>)
plt.ylabel(<span class="hljs-string">'Frequency'</span>)
plt.show()
</code></pre>
<p>This histogram illustrates the distribution of order quantities, showing how often customers order different quantities of products. It helps you understand your typical order sizes and identify any unusual patterns.</p>
<p><strong>Key Insights from Visualizations:</strong></p>
<ul>
<li>The line chart reveals trends in total sales over time.</li>
<li>The scatter plot unveils potential relationships between sales and profit for different customer segments.</li>
<li>The bar chart clearly shows which product categories generate the most sales.</li>
<li>The histogram provides insights into how order quantities are distributed.</li>
</ul>
<p>Remember: These are just a few examples. You can experiment with different types of plots and customizations to uncover even more insights from your data. Matplotlib offers a rich set of tools to explore your data visually and communicate your findings effectively.</p>
<h5 id="heading-full-code-2">Full code:</h5>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Convert 'Order Date' to datetime for proper plotting</span>
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>])

<span class="hljs-comment"># Group sales by order date and sum them up</span>
daily_sales = df.groupby(<span class="hljs-string">'Order Date'</span>)[<span class="hljs-string">'Sales'</span>].sum()

plt.figure(figsize=(<span class="hljs-number">12</span>, <span class="hljs-number">6</span>))
plt.plot(daily_sales, marker=<span class="hljs-string">'o'</span>)  <span class="hljs-comment"># Plot line chart with markers for data points</span>
plt.title(<span class="hljs-string">'Total Sales Over Time'</span>)
plt.xlabel(<span class="hljs-string">'Order Date'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.xticks(rotation=<span class="hljs-number">45</span>) 
plt.grid(axis=<span class="hljs-string">'y'</span>)
plt.show()


<span class="hljs-comment"># Create a scatter plot for each segment</span>
segments = df[<span class="hljs-string">'Segment'</span>].unique()
colors = [<span class="hljs-string">'blue'</span>, <span class="hljs-string">'green'</span>, <span class="hljs-string">'orange'</span>]  <span class="hljs-comment"># Choose distinct colors for each segment</span>

plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>))
<span class="hljs-keyword">for</span> i, segment <span class="hljs-keyword">in</span> enumerate(segments):
    segment_data = df[df[<span class="hljs-string">'Segment'</span>] == segment]
    plt.scatter(segment_data[<span class="hljs-string">'Sales'</span>], segment_data[<span class="hljs-string">'Profit'</span>], c=colors[i], label=segment)

plt.title(<span class="hljs-string">'Sales vs. Profit by Segment'</span>)
plt.xlabel(<span class="hljs-string">'Sales'</span>)
plt.ylabel(<span class="hljs-string">'Profit'</span>)
plt.legend()
plt.show()

<span class="hljs-comment"># Calculate total sales by category</span>
sales_by_category = df.groupby(<span class="hljs-string">'Category'</span>)[<span class="hljs-string">'Sales'</span>].sum()

plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>))
plt.bar(sales_by_category.index, sales_by_category.values, color=<span class="hljs-string">'skyblue'</span>)
plt.title(<span class="hljs-string">'Total Sales by Category'</span>)
plt.xlabel(<span class="hljs-string">'Category'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.xticks(rotation=<span class="hljs-number">45</span>)
plt.show()

plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">6</span>))
plt.hist(df[<span class="hljs-string">'Quantity'</span>], bins=<span class="hljs-number">5</span>, color=<span class="hljs-string">'salmon'</span>, alpha=<span class="hljs-number">0.7</span>, rwidth=<span class="hljs-number">0.8</span>)
plt.title(<span class="hljs-string">'Distribution of Order Quantities'</span>)
plt.xlabel(<span class="hljs-string">'Quantity'</span>)
plt.ylabel(<span class="hljs-string">'Frequency'</span>)
plt.show()
</code></pre>
<h2 id="heading-4-data-analysis-fundamentals-the-art-of-making-sense-of-data">4. Data Analysis Fundamentals: The Art of Making Sense of Data</h2>
<p>In the realm of data science, raw data is merely the starting point. The true value lies in the insights that can be gleaned from it. This chapter equips you with the essential skills to transform data into actionable knowledge, enabling you to make informed decisions and drive impactful change.</p>
<p>You'll begin by understanding the fundamental building blocks of data: data types and structures. Grasping the difference between categorical and numerical data is crucial for choosing the right analysis techniques and ensuring accurate results.</p>
<p>Next, you'll delve into descriptive statistics, the bedrock of data analysis. You'll learn to calculate central tendency measures (mean, median, mode) and dispersion measures (range, variance, standard deviation) to summarize and understand your data's key characteristics.</p>
<p>Data cleaning and preparation are often overlooked, but these steps are essential for ensuring the quality and reliability of your analysis. You'll build one what we just discussed and learn some best practices for handling missing values, identifying and addressing duplicates, and dealing with outliers that can skew your results.</p>
<p>Finally, you'll embark on the journey of exploratory data analysis (EDA). This iterative process involves using visualization techniques and summary statistics to uncover patterns, generate hypotheses, and gain a deeper understanding of your data.</p>
<p>By the end of this chapter, you'll have a solid grasp of the fundamental concepts and techniques of data analysis. You'll be able to confidently explore and interpret datasets, paving the way for more advanced analysis and modeling techniques.</p>
<p>Remember, data is not just numbers and categories – it's a story waiting to be told. By mastering these foundational skills, you'll become a skilled storyteller, capable of extracting meaningful insights and driving data-informed decision-making.</p>
<h3 id="heading-41-data-types-and-structures">4.1 Data Types and Structures</h3>
<p>In data analysis, understanding the type of data you are working with is fundamental. Just as a carpenter selects the right tool for a specific job, a data analyst chooses the appropriate technique based on the nature of the data.  </p>
<p>Data types and data structures form the vocabulary of data analysis, guiding you toward the most effective methods for extracting insights.</p>
<p>There are two primary categories of data:</p>
<ol>
<li><strong>Categorical Data:</strong> This type represents qualitative information, classifying data into distinct groups or categories. Examples include customer segments, product categories, or regions. Categorical data is not inherently numerical, and calculations like averages or sums are not meaningful.</li>
<li><strong>Numerical Data:</strong> This type represents quantitative information, describing quantities or measurements. Examples include sales figures, prices, ages, or temperatures. Numerical data lends itself to mathematical operations, statistical analysis, and a wider range of visualization techniques.</li>
</ol>
<h4 id="heading-why-data-types-matter">Why Data Types Matter</h4>
<p>The distinction between categorical and numerical data is crucial because it dictates the types of analysis and visualization that are appropriate. </p>
<p>For instance, you might use a bar chart to visualize the distribution of categorical data (for example, sales by category), while a histogram would be more suitable for numerical data (for example, distribution of customer ages).</p>
<p><strong>Key Considerations:</strong></p>
<ul>
<li><strong>Ordinal vs. Nominal Data:</strong> Categorical data can be further classified as ordinal (categories with a natural order, such as "low," "medium," "high") or nominal (categories without an inherent order, such as "red," "green," "blue"). This distinction can influence how you analyze and visualize the data.</li>
<li><strong>Discrete vs. Continuous Data:</strong> Numerical data can be either discrete (countable values, such as the number of items sold) or continuous (infinitely many possible values within a range, such as temperature or height). Understanding this difference can guide your choice of statistical tests and visualizations.</li>
</ul>
<p><strong>Practical Tips:</strong></p>
<ul>
<li><strong>Examine Your Data:</strong> Carefully inspect your dataset to identify the type and structure of each variable.</li>
<li><strong>Consult Metadata:</strong> Refer to data dictionaries or documentation to understand the intended meaning and type of each variable.</li>
<li><strong>Avoid Assumptions:</strong> Don't assume that data is numerical just because it's represented by numbers. Zip codes, phone numbers, and even some product codes are categorical in nature.</li>
</ul>
<h4 id="heading-some-examples">Some Examples:</h4>
<p>In this section, we'll dive into practical examples across various industries to demonstrate the pivotal role categorical data plays in decision-making and problem-solving.  </p>
<p>Remember, categorical data represents groups or categories, and its analysis focuses on understanding distributions, relationships, and frequencies.</p>
<p><strong>1. Marketing: Targeted Campaigns</strong></p>
<p>Imagine a clothing retailer seeking to optimize their marketing efforts. By segmenting their customer base into distinct categories based on demographics like age group, gender, and income level, they can tailor their campaigns to resonate with specific audiences.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Sample customer data</span>
data = {<span class="hljs-string">'Age Group'</span>: [<span class="hljs-string">'18-24'</span>, <span class="hljs-string">'25-34'</span>, <span class="hljs-string">'35-44'</span>, <span class="hljs-string">'45-54'</span>, <span class="hljs-string">'55+'</span>],
        <span class="hljs-string">'Gender'</span>: [<span class="hljs-string">'Male'</span>, <span class="hljs-string">'Female'</span>, <span class="hljs-string">'Female'</span>, <span class="hljs-string">'Male'</span>, <span class="hljs-string">'Female'</span>],
        <span class="hljs-string">'Income Level'</span>: [<span class="hljs-string">'Low'</span>, <span class="hljs-string">'Medium'</span>, <span class="hljs-string">'High'</span>, <span class="hljs-string">'High'</span>, <span class="hljs-string">'Medium'</span>]}

df = pd.DataFrame(data)
</code></pre>
<p><strong>Analysis:</strong> The retailer can use Pandas to analyze purchase patterns within each segment. For instance, they might discover that the 18-24 age group primarily purchases trendy items, while the 45-54 age group prefers classic styles.  </p>
<p>This information allows them to create targeted marketing campaigns that speak directly to each segment's preferences.</p>
<p><strong>2. Healthcare: Treatment Efficacy Analysis</strong></p>
<p>Pharmaceutical companies heavily rely on categorical data to assess the effectiveness of new drugs. By classifying patients into groups based on disease type, they can analyze treatment outcomes within each category.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sample patient data</span>
data = {<span class="hljs-string">'Disease Type'</span>: [<span class="hljs-string">'Cancer'</span>, <span class="hljs-string">'Diabetes'</span>, <span class="hljs-string">'Cancer'</span>, <span class="hljs-string">'Heart Disease'</span>, <span class="hljs-string">'Diabetes'</span>],
        <span class="hljs-string">'Treatment Response'</span>: [<span class="hljs-string">'Positive'</span>, <span class="hljs-string">'Negative'</span>, <span class="hljs-string">'Positive'</span>, <span class="hljs-string">'Neutral'</span>, <span class="hljs-string">'Positive'</span>]}

df = pd.DataFrame(data)
</code></pre>
<p><strong>Analysis:</strong> In this scenario, the pharmaceutical company can use Pandas to determine the treatment response rates for each disease type. They might find that the new drug is more effective for cancer patients than for those with diabetes, allowing them to refine treatment protocols and target specific patient populations.</p>
<p><strong>3. Education: Academic Performance Tracking</strong></p>
<p>Educational institutions utilize categorical data to monitor student progress and evaluate the effectiveness of educational programs. By grouping students by grade level and demographic factors, they can identify trends in academic performance and address potential disparities.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sample student data</span>
data = {<span class="hljs-string">'Grade Level'</span>: [<span class="hljs-string">'Freshman'</span>, <span class="hljs-string">'Sophomore'</span>, <span class="hljs-string">'Junior'</span>, <span class="hljs-string">'Senior'</span>, <span class="hljs-string">'Sophomore'</span>],
        <span class="hljs-string">'Gender'</span>: [<span class="hljs-string">'Female'</span>, <span class="hljs-string">'Male'</span>, <span class="hljs-string">'Female'</span>, <span class="hljs-string">'Male'</span>, <span class="hljs-string">'Female'</span>],
        <span class="hljs-string">'Ethnicity'</span>: [<span class="hljs-string">'Hispanic'</span>, <span class="hljs-string">'White'</span>, <span class="hljs-string">'Asian'</span>, <span class="hljs-string">'Black'</span>, <span class="hljs-string">'White'</span>]}

df = pd.DataFrame(data)
</code></pre>
<p><strong>Analysis:</strong> A school district could use this data to analyze graduation rates across different demographics. For instance, they might find that graduation rates are lower for certain ethnic groups or genders, prompting them to implement targeted interventions to support those students.</p>
<p><strong>4. Retail: Inventory Optimization</strong></p>
<p>Retailers categorize their products to streamline inventory management and analyze sales patterns. This categorization allows them to track inventory levels for each product type, forecast demand, and optimize stock allocation based on seasonal trends.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sample product data</span>
data = {<span class="hljs-string">'Product'</span>: [<span class="hljs-string">'Smartphone'</span>, <span class="hljs-string">'Laptop'</span>, <span class="hljs-string">'Headphones'</span>, <span class="hljs-string">'T-Shirt'</span>, <span class="hljs-string">'Shoes'</span>],
        <span class="hljs-string">'Category'</span>: [<span class="hljs-string">'Electronics'</span>, <span class="hljs-string">'Electronics'</span>, <span class="hljs-string">'Electronics'</span>, <span class="hljs-string">'Clothing'</span>, <span class="hljs-string">'Clothing'</span>]}

df = pd.DataFrame(data)
</code></pre>
<p><strong>Analysis:</strong> An online retailer might use this data to determine which product categories are most popular during different times of the year. This information could inform inventory decisions, ensuring that popular items are well-stocked during peak demand periods.</p>
<p><strong>5. Social Sciences: Public Opinion Analysis</strong></p>
<p>Social scientists frequently analyze survey responses to gauge public opinion on various issues. Categorical data, such as responses to Likert scale questions (for example, "strongly agree," "agree," "neutral," "disagree," "strongly disagree"), are crucial for understanding attitudes and beliefs.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sample survey data</span>
data = {<span class="hljs-string">'Question'</span>: [<span class="hljs-string">'Q1'</span>, <span class="hljs-string">'Q2'</span>, <span class="hljs-string">'Q3'</span>, <span class="hljs-string">'Q4'</span>, <span class="hljs-string">'Q5'</span>],
        <span class="hljs-string">'Response'</span>: [<span class="hljs-string">'Agree'</span>, <span class="hljs-string">'Disagree'</span>, <span class="hljs-string">'Neutral'</span>, <span class="hljs-string">'Strongly Agree'</span>, <span class="hljs-string">'Disagree'</span>]}

df = pd.DataFrame(data)
</code></pre>
<p><strong>Analysis:</strong> Political pollsters might use this data to assess voter sentiment towards a particular candidate or policy. By analyzing the frequency of different responses, they can gain insights into public opinion trends and tailor their communication strategies accordingly.</p>
<p><strong>6. Manufacturing: Quality Control</strong></p>
<p>In manufacturing, classifying production defects into categories (for example, cosmetic, functional, critical) helps prioritize quality control efforts.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sample defect data</span>
data = {<span class="hljs-string">'Defect Type'</span>: [<span class="hljs-string">'Cosmetic'</span>, <span class="hljs-string">'Functional'</span>, <span class="hljs-string">'Critical'</span>, <span class="hljs-string">'Cosmetic'</span>, <span class="hljs-string">'Functional'</span>],
        <span class="hljs-string">'Product ID'</span>: [<span class="hljs-string">'P1'</span>, <span class="hljs-string">'P2'</span>, <span class="hljs-string">'P3'</span>, <span class="hljs-string">'P1'</span>, <span class="hljs-string">'P4'</span>]}

df = pd.DataFrame(data)
</code></pre>
<p><strong>Analysis:</strong> A car manufacturer can track the frequency of different defect types to identify areas for improvement in the production process. For example, if cosmetic defects are more prevalent than functional ones, they might focus on improving the finishing process.</p>
<p><strong>7. Human Resources: Workforce Analysis</strong></p>
<p>Human resources departments utilize categorical data to analyze workforce composition and compensation trends. Grouping employees by job title allows them to assess diversity and inclusion within the organization.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Sample employee data</span>
data = {<span class="hljs-string">'Job Title'</span>: [<span class="hljs-string">'Manager'</span>, <span class="hljs-string">'Engineer'</span>, <span class="hljs-string">'Analyst'</span>, <span class="hljs-string">'Manager'</span>, <span class="hljs-string">'Engineer'</span>],
        <span class="hljs-string">'Gender'</span>: [<span class="hljs-string">'Male'</span>, <span class="hljs-string">'Female'</span>, <span class="hljs-string">'Female'</span>, <span class="hljs-string">'Female'</span>, <span class="hljs-string">'Male'</span>]}

df = pd.DataFrame(data)
</code></pre>
<p><strong>Analysis:</strong> An HR team could use this data to examine the gender distribution across different job titles. If they identify underrepresentation in certain roles, they can implement initiatives to promote diversity and equal opportunity.</p>
<p>These examples demonstrate how categorical data is a versatile tool for gaining insights and making informed decisions in diverse industries. By leveraging Pandas' capabilities to manipulate, analyze, and visualize categorical data, you can uncover hidden patterns, identify trends, and empower your organization to make strategic choices that drive success.</p>
<p>By mastering the fundamentals of data types and structures, you'll lay a solid foundation for your data analysis journey. This knowledge will guide you in selecting appropriate techniques, ensuring accurate results, and ultimately, unlocking the full potential of your data to drive informed decision-making.</p>
<h3 id="heading-42-descriptive-statistics">4.2 Descriptive Statistics</h3>
<p>Imagine you're handed a massive dataset filled with numbers. How can you make sense of it all? That's where descriptive statistics come in—your trusty guide to summarizing and understanding the key characteristics of your data.</p>
<p>Descriptive statistics are like a compass for data exploration, providing a clear overview of the landscape. They reveal central tendencies, the "typical" or "average" values in your dataset. They illuminate dispersion, showing how spread out or clustered your data is. And they offer glimpses into the shape of your data, hinting at potential skewness or unusual patterns.</p>
<p>In this section, we'll delve into essential descriptive statistics, including measures of central tendency (mean, median, mode), measures of dispersion (range, variance, standard deviation), measures of shape (skewness, kurtosis), and frequency distributions. You'll learn how to calculate these statistics using Python and Pandas, empowering you to extract meaningful insights from your data.</p>
<p>Think of it as a detective examining clues at a crime scene. Descriptive statistics are your magnifying glass, helping you identify patterns, anomalies, and relationships that might otherwise remain hidden. By mastering these fundamental tools, you'll be well-equipped to make informed decisions, build accurate models, and communicate your findings effectively.</p>
<p>So, are you ready to unveil the secrets hidden within your data? Let's dive into the fascinating world of descriptive statistics and unlock the power of your data to drive meaningful change.</p>
<h4 id="heading-421-measures-of-central-tendency">4.2.1 Measures of Central Tendency:</h4>
<p>Understanding the central tendency of your data is like finding the heart of a story – it gives you a sense of the typical or average value. These measures provide a quick snapshot of your data's central location, offering valuable insights into its overall behavior. </p>
<p>Let's delve into the three main measures of central tendency:</p>
<h5 id="heading-mean">Mean</h5>
<p>The mean, often referred to as the average, is a fundamental statistical measure that provides a single numerical value representing the central tendency of a dataset. It's calculated by summing up all the values in the dataset and then dividing this sum by the total number of values.</p>
<p>The mean is a powerful tool in data analysis for several reasons:</p>
<ul>
<li><strong>Summarization:</strong> It condenses a large amount of data into a single representative value, making it easier to grasp the overall picture. For example, the mean income of a city's residents tells you a lot about the city's economic situation.</li>
<li><strong>Comparison:</strong>  It allows for easy comparison between different groups. For instance, the mean test scores of two classes can reveal which class performed better overall.</li>
<li><strong>Estimation:</strong> In situations where individual data points are unknown, the mean can be used to estimate missing values based on the overall trend.</li>
<li><strong>Decision-Making:</strong> The mean can be used as a benchmark for decision-making. For example, a company might set production goals based on the mean output of its employees.</li>
</ul>
<p><strong>Detailed Calculation:</strong></p>
<ol>
<li><strong>Summation:</strong> Add up all the values in your dataset. For example, if your dataset is {5, 10, 15, 20}, the sum is 5 + 10 + 15 + 20 = 50.</li>
<li><strong>Division:</strong> Divide the sum by the total number of values in the dataset. In our example, there are 4 values, so the mean is 50 / 4 = 12.5.</li>
</ol>
<p>Here's the mathematical formula for calculating the mean:</p>
<p>Mean (x̄) = (Σx) / n</p>
<p>Where:</p>
<ul>
<li>x̄ is the symbol for the mean</li>
<li>Σx represents the sum of all values (x)</li>
<li>n is the total number of values</li>
</ul>
<p>The mean provides a measure of the "center" of your data. If the data points were balanced on a seesaw, the mean would be the point where the seesaw balances perfectly. A higher mean generally indicates that the individual values in the dataset tend to be higher. Conversely, a lower mean suggests that the values tend to be lower.</p>
<p><strong>Significance of Outliers:</strong></p>
<p>One of the most important considerations when interpreting the mean is its sensitivity to outliers – extreme values that deviate significantly from the rest of the data. Since the mean takes into account every value in the dataset, a single outlier can drastically pull the mean towards it, potentially leading to a misleading representation of the central tendency.</p>
<p>For example, consider a dataset representing the salaries of 10 employees: {30,000, 35,000, 40,000, 45,000, 50,000, 55,000, 60,000, 65,000, 500,000}. The outlier salary of $500,000 significantly inflates the mean, making it appear that the average salary is much higher than it actually is for most employees.</p>
<p><strong>When to Use the Mean:</strong></p>
<p>The mean is most appropriate when:</p>
<ul>
<li>Your data is normally distributed (or approximately so), meaning it follows a bell-shaped curve.</li>
<li>You want a single value that represents the typical value in your dataset.</li>
<li>Outliers are not a significant concern, or you have taken steps to address them.</li>
</ul>
<p><strong>Alternatives to the Mean:</strong></p>
<p>When outliers are present or your data is not normally distributed, consider using the median or mode as alternative measures of central tendency. The median is the middle value when the data is ordered, and the mode is the most frequent value. These measures are less sensitive to extreme values and can provide a more accurate representation of the central tendency in such cases.</p>
<h5 id="heading-median">Median</h5>
<p>The median is a fundamental statistical measure that pinpoints the central value of a dataset when it's arranged in ascending (or descending) order. Imagine your data points lined up like soldiers in a row, from shortest to tallest. The median is the soldier standing right in the middle, with an equal number of soldiers on either side.</p>
<p>The median isn't calculated using a single formula like the mean. Instead, the calculation depends on whether you have an odd or even number of data points:</p>
<p><strong>Odd Number of Data Points:</strong></p>
<ul>
<li>Formula: Median = Value of the ((n + 1) / 2)th term</li>
<li>Explanation:  Here, 'n' represents the total number of data points. By adding 1 to 'n' and dividing by 2, you find the position of the middle value in the ordered dataset.</li>
</ul>
<p><strong>Even Number of Data Points:</strong></p>
<ul>
<li>Formula: Median = (Value of the (n / 2)th term + Value of the ((n / 2) + 1)th term) / 2</li>
<li>Explanation: In this case, there are two middle values. The formula averages these two values to find the median.</li>
</ul>
<p><strong>Example: Applying the Formula:</strong></p>
<p>Let's consider the dataset representing the heights (in inches) of 5 students: {60, 62, 64, 68, 70}.</p>
<ol>
<li>Sorting: The data is already in ascending order.</li>
</ol>
<p><strong>Odd Number of Data Points:</strong> We have 5 data points, which is odd.  Therefore, we use the formula: Median = Value of the ((n + 1) / 2)th term</p>
<ul>
<li>Here, n = 5, so (n + 1) / 2 = 3</li>
<li>The median is the value of the 3rd term, which is 64 inches.</li>
</ul>
<p>Now, let's add another student with a height of 66 inches, making the dataset: {60, 62, 64, 66, 68, 70}.</p>
<ol start="2">
<li>Sorting: The data remains in ascending order.</li>
</ol>
<p><strong>Even Number of Data Points:</strong> Now we have 6 data points, which is even. We use the formula: Median = (Value of the (n / 2)th term + Value of the ((n / 2) + 1)th term) / 2</p>
<ul>
<li>Here, n = 6, so n / 2 = 3 and (n / 2) + 1 = 4</li>
<li>The median is the average of the 3rd and 4th terms, which is (64 + 66) / 2 = 65 inches.</li>
</ul>
<p><strong>Purpose and Use:</strong></p>
<p>The median's superpower lies in its robustness against outliers:</p>
<ul>
<li><strong>Resilience to Skewed Data:</strong>  Unlike the mean, which can be easily skewed by extreme values, the median remains relatively unaffected. In datasets with a few exceptionally high or low values, the median provides a more accurate representation of the "typical" value.</li>
<li><strong>Fairness in Representation:</strong> In scenarios where a few individuals earn disproportionately high incomes, the median income better reflects the experience of the majority than the mean, which would be inflated by those high earners.</li>
<li><strong>Decision Making with Skewed Data:</strong> When analyzing skewed data (such as income distributions, house prices, or reaction times), the median is often a more appropriate measure for decision-making than the mean.</li>
<li><strong>Ordinal Data:</strong>  The median is particularly useful for ordinal data, where values have a natural order but the differences between them may not be meaningful (for example, rating scales, rankings).</li>
</ul>
<p><strong>Detailed Calculation:</strong></p>
<p><strong>Sorting:</strong> Arrange your data points in ascending order.</p>
<p><strong>Odd Number of Data Points:</strong> If you have an odd number of data points, the median is simply the middle value. For example, in the dataset {3, 7, 9, 12, 15}, the median is 9.</p>
<p><strong>Even Number of Data Points:</strong> If you have an even number of data points, identify the two middle values. The median is the average of these two values. For example, in the dataset {2, 5, 8, 11}, the two middle values are 5 and 8, so the median is (5 + 8) / 2 = 6.5.</p>
<p>The median tells a compelling story about your data:</p>
<ul>
<li><strong>Central Tendency:</strong> It reveals the value that splits the dataset in half, with 50% of the data points falling below and 50% above. This gives you a clear sense of the "center" of your data.</li>
<li><strong>Robustness:</strong>  It's a reliable measure even when outliers are present. If your data includes a few extremely high or low values, the median remains stable and provides a more representative picture of the central tendency than the mean.</li>
</ul>
<p><strong>Example: Income Distribution</strong></p>
<p>Imagine a neighborhood with five households and the following annual incomes: $30,000, $45,000, $50,000, $62,000, and $80,000.</p>
<p>The <strong>mean income</strong> is ($30,000 + $45,000 + $50,000 + $62,000 + $80,000) / 5 = $53,400. This might make it seem like the "average" household is relatively well-off.</p>
<p>However, the <strong>median income</strong> is $50,000. This value more accurately reflects the typical income in the neighborhood, as it's not influenced by the highest earner ($80,000).</p>
<p><strong>When to Use the Median:</strong></p>
<ul>
<li>Your data is skewed (not normally distributed).</li>
<li>Outliers are present or suspected.</li>
<li>You're dealing with ordinal data (for example, rankings, ratings).</li>
<li>You want a measure of central tendency that is robust to extreme values.</li>
</ul>
<p><strong>Beyond the Median:</strong></p>
<p>While the median provides valuable insights into your data's central tendency, it's important to consider it in conjunction with other descriptive statistics. Examining the range, interquartile range (IQR), and visual representations like box plots can give you a more comprehensive understanding of your data's distribution and variability.</p>
<h5 id="heading-mode">Mode</h5>
<p>The mode, in its simplest form, is the value or values that appear most frequently within a dataset. It's like a popularity contest where the value with the most votes wins. In essence, the mode highlights the peak(s) in the distribution of your data, revealing which category or value dominates the scene.</p>
<p><strong>Unveiling the Mode: Calculation and Types</strong></p>
<p>Unlike the mean and median, the mode doesn't rely on complex formulas. Instead, it's about observation and counting:</p>
<ol>
<li><strong>Identify Unique Values:</strong> List out all the distinct values present in your dataset.</li>
<li><strong>Count Frequencies:</strong> Determine how many times each unique value appears.</li>
<li><strong>The Winner(s):</strong> The value(s) with the highest frequency is/are the mode(s).</li>
</ol>
<p><strong>Types of Mode:</strong></p>
<ul>
<li><strong>Unimodal:</strong> A dataset with a single mode.</li>
<li><strong>Bimodal:</strong> A dataset with two modes.</li>
<li><strong>Multimodal:</strong> A dataset with three or more modes.</li>
<li><strong>No Mode:</strong> A dataset where all values occur with equal frequency.</li>
</ul>
<p><strong>Purpose and Use:</strong></p>
<p>The mode is a versatile tool with specific applications:</p>
<ul>
<li><strong>Categorical Data:</strong> It shines when dealing with categorical data (for example, colors, brands, types of cars) where the mean and median are not applicable. The mode tells you the most popular category.</li>
<li><strong>Discrete Data:</strong> It's also handy for discrete data (for example, the number of children in a family, shoe sizes) where values are distinct and countable. The mode reveals the most common value(s).</li>
<li><strong>Customer Preferences:</strong> Businesses often use the mode to understand customer preferences. For instance, the most frequently purchased product is the mode.</li>
<li><strong>Public Opinion:</strong> In surveys and polls, the mode can indicate the most popular opinion or choice among respondents.</li>
<li><strong>Distribution Insights:</strong> While the mode might not pinpoint the exact center, it offers insights into the shape of your data's distribution. Multiple modes suggest clusters or groups within the data.</li>
</ul>
<p>Interpreting the mode is straightforward:</p>
<ul>
<li><strong>Most Common:</strong> The mode(s) simply represent the most frequent or popular value(s) in your dataset.</li>
<li><strong>Distribution Peaks:</strong> If your data were visualized in a histogram, the mode(s) would correspond to the tallest bar(s), representing the peaks in the distribution.</li>
<li><strong>Context Matters:</strong> The meaning of the mode depends on the context of your data. For example, if the mode of transportation in a city is "car," it tells you that driving is the most common way people get around.</li>
</ul>
<p>Imagine you survey a group of friends about their favorite ice cream flavors:</p>
<ul>
<li>Vanilla: 5 votes</li>
<li>Chocolate: 7 votes</li>
<li>Strawberry: 3 votes</li>
</ul>
<p>In this case, the mode is "Chocolate" because it received the most votes. This tells you that among your friends, chocolate is the most popular ice cream flavor.</p>
<p><strong>When to Use the Mode:</strong></p>
<ul>
<li>You're dealing with categorical or nominal data.</li>
<li>You're interested in the most frequent or popular category or value.</li>
<li>You want to understand the peaks in your data's distribution.</li>
</ul>
<p><strong>Mode's Limitations:</strong></p>
<p>While the mode is valuable, it has limitations:</p>
<ul>
<li><strong>Multiple Modes:</strong> The presence of multiple modes can make interpretation less clear-cut.</li>
<li><strong>Not a Central Value:</strong> Unlike the mean and median, the mode doesn't necessarily represent the central value of the dataset.</li>
</ul>
<p><strong>Beyond the Mode:</strong></p>
<p>The mode is just one piece of the puzzle. For a complete picture of your data, consider using the mode in conjunction with other descriptive statistics like the mean, median, range, and standard deviation.</p>
<h4 id="heading-navigating-the-central-tendency-landscape-choosing-the-right-measure">Navigating the Central Tendency Landscape: Choosing the Right Measure</h4>
<p>Selecting the most suitable measure of central tendency—mean, median, or mode—is crucial for accurately interpreting and summarizing your data. Your decision should be guided by two key factors: the type of data you have and the distribution of your data.</p>
<p><strong>1. Data Type:</strong></p>
<p>The nature of your data significantly influences your choice of central tendency measure:</p>
<ul>
<li><strong>Categorical Data:</strong> When dealing with categories (for example, colors, brands, types of animals), the mode is your only option. It identifies the most frequent or popular category, providing valuable insights into preferences or trends.</li>
<li><strong>Numerical Data:</strong> For numerical data, you have more flexibility. The choice between mean and median hinges on the distribution of your data and the presence of outliers.</li>
</ul>
<p><strong>2. Distribution of Data:</strong></p>
<p>The shape of your data's distribution plays a crucial role in determining the most appropriate measure of central tendency:</p>
<ul>
<li><strong>Symmetrical Distribution:</strong> In a perfectly symmetrical distribution (like a bell curve), the mean, median, and mode are all equal and coincide at the center. In such cases, any of these measures can be used to represent the central tendency.</li>
</ul>
<p><strong>Skewed Distribution:</strong> When your data is skewed, the mean, median, and mode diverge.</p>
<ul>
<li><strong>Positive Skew:</strong> The tail of the distribution extends to the right. The mean is pulled towards the tail and becomes higher than the median and mode. In this scenario, the median is often a better representation of the central tendency because it is less affected by the extreme values in the tail.</li>
<li><strong>Negative Skew:</strong> The tail of the distribution extends to the left. The mean is dragged down by the lower values in the tail and becomes lower than the median and mode. Here, again, the median is preferred over the mean due to its resilience to outliers.</li>
</ul>
<p><strong>Outliers:</strong></p>
<p>Outliers, those data points far removed from the rest, can significantly influence the mean, skewing it towards their extreme values. The median, on the other hand, is relatively unaffected by outliers. Therefore, when outliers are present, the median is generally a more robust and representative measure of central tendency.</p>
<p>To help you choose, here's a simple flowchart:</p>
<p><strong>Is your data categorical?</strong></p>
<ul>
<li>Yes: Use the Mode</li>
<li>No: Proceed to step 2</li>
</ul>
<p><strong>Does your data have outliers?</strong></p>
<ul>
<li>Yes: Use the Median</li>
<li>No: Proceed to step 3</li>
</ul>
<p><strong>Is your data normally distributed (or approximately so)?</strong></p>
<ul>
<li>Yes: Use the Mean</li>
<li>No: Use the Median (or consider both mean and median for a nuanced view)</li>
</ul>
<p><strong>Example: Housing Prices</strong></p>
<p>Imagine you're analyzing housing prices in a neighborhood.  If there's one exceptionally expensive mansion, it will significantly raise the mean price, making it appear that homes in the neighborhood are more expensive than they actually are for the majority of residents. In this case, the median price would provide a more accurate representation of the typical house price.</p>
<p>By understanding the nuances of your data and considering the factors discussed above, you can confidently choose the most appropriate measure of central tendency, ensuring that your analysis is both accurate and meaningful.</p>
<h3 id="heading-422-measures-of-dispersion-variability">4.2.2 Measures of Dispersion (Variability):</h3>
<h5 id="heading-range-the-difference-between-the-highest-and-lowest-values">Range: The difference between the highest and lowest values.</h5>
<p>Imagine your data as a flock of birds soaring through the sky. The range is the distance between the highest-flying bird and the lowest-flying bird—the full wingspan of your data. </p>
<p>In statistical terms, it's simply the difference between the maximum and minimum values in your dataset.</p>
<p>The range provides a quick snapshot of your data's spread. It answers the question: "How far apart are the extremes?" This is valuable for:</p>
<ul>
<li><strong>Identifying Outliers:</strong>  A large range might signal the presence of outliers—data points that deviate significantly from the norm. These could be errors or genuinely extreme cases that warrant further investigation.</li>
<li><strong>Quality Control:</strong> In manufacturing, the range can help monitor the consistency of products. A narrow range indicates that items are being produced with uniform specifications.</li>
<li><strong>Setting Boundaries:</strong> When designing experiments or surveys, the range can guide you in determining appropriate scales or limits for your measurements.</li>
<li><strong>Initial Data Exploration:</strong> The range is a handy tool for getting a feel for your data before diving into more complex analyses.</li>
</ul>
<p>Calculating the range is refreshingly simple:</p>
<p>Range = Maximum Value - Minimum Value</p>
<p><strong>Interpretation:</strong> A larger range indicates greater variability in your data, while a smaller range suggests more consistency. However, don't rely solely on the range. It's sensitive to outliers and doesn't tell you anything about the distribution of values within the range.</p>
<p><strong>Temperature Swings Example:</strong> Consider daily temperature readings over a week: 55°F, 62°F, 70°F, 78°F, 85°F, 68°F, 58°F. The range is 85°F - 55°F = 30°F. This tells you that the temperature varied by 30 degrees throughout the week. </p>
<p>If you were planning outdoor activities, this information would be crucial for choosing appropriate attire and preparing for temperature fluctuations.</p>
<p><strong>Practical Advice:</strong> Don't stop at the range. Pair it with other descriptive statistics (like the interquartile range or standard deviation) and visualizations (like histograms or box plots) for a richer understanding of your data's distribution. </p>
<p>Remember, the range is just the first step on your journey to unlocking the full story hidden within your numbers.</p>
<h5 id="heading-variance-the-average-of-the-squared-deviations-from-the-mean">Variance: The average of the squared deviations from the mean.</h5>
<p>Imagine your data as a group of individuals with diverse personalities. Variance quantifies how much those personalities deviate from the average, painting a picture of your data's diversity. </p>
<p>Technically, it's the average of the squared differences of each data point from the mean. Why square the differences? To ensure that positive and negative deviations don't cancel each other out and to amplify larger deviations.</p>
<p>Variance serves as your data's pulse, revealing the rhythm of its variability:</p>
<ul>
<li><strong>Risk Assessment:</strong> In finance, variance is a cornerstone of risk assessment. A high variance in stock prices signals greater volatility and potential for both higher gains and losses. Understanding this allows investors to make informed decisions tailored to their risk tolerance.</li>
<li><strong>Quality Control:</strong> In manufacturing, variance is a critical metric for maintaining product consistency. High variance in measurements could indicate issues with the production process, prompting corrective actions to ensure quality standards are met.</li>
<li><strong>Experiment Design:</strong> Researchers use variance to determine the effectiveness of treatments or interventions. If the variance within treatment groups is high, it might mask the true effect of the treatment, making it harder to draw meaningful conclusions.</li>
<li><strong>Data Exploration:</strong> Variance can uncover hidden patterns or subgroups within your data. Unexplained high variance might signal that your data is comprised of distinct groups with different characteristics.</li>
</ul>
<p>Calculating the variance might seem intimidating, but the concept is intuitive:</p>
<ol>
<li>Calculate the mean (average) of your data.</li>
<li>Subtract the mean from each data point and square the result.</li>
<li>Sum up all the squared differences.</li>
<li>Divide the sum by the number of data points.</li>
</ol>
<p><strong>Formula:</strong></p>
<p>σ² = Σ(xᵢ - μ)² / N (for population variance) </p>
<p>s² = Σ(xᵢ - x̄)² / (n - 1) (for sample variance)</p>
<p>Where:</p>
<ul>
<li>σ² (sigma squared) is the population variance</li>
<li>s² is the sample variance</li>
<li>xᵢ represents each individual data point</li>
<li>μ (mu) is the population mean</li>
<li>x̄ is the sample mean</li>
<li>N is the population size</li>
<li>n is the sample size</li>
</ul>
<p><strong>Interpretation:</strong> A higher variance indicates greater dispersion and diversity within your data, while a lower variance suggests more uniformity. </p>
<p>Remember that variance is expressed in squared units, which can make it difficult to directly compare with your original data. For this reason, we often use the standard deviation (the square root of the variance) as a more interpretable measure of variability.</p>
<p><strong>Test Scores Example:</strong> Imagine that two classes took the same exam. Class A has a mean score of 80 with a variance of 25, while Class B has the same mean score but a variance of 100. This means that the scores in Class B are more spread out than those in Class A. In Class B, you might find students who excelled and others who struggled, while Class A's performance was more consistent.</p>
<p><strong>Practical Advice:</strong> Don't be discouraged by the formula. Most statistical software packages can easily calculate variance for you. Focus on understanding its meaning and implications for your data. Remember, variance is a powerful tool for uncovering insights that can drive better decision-making and problem-solving.</p>
<h5 id="heading-standard-deviation-the-square-root-of-the-variance-indicating-how-spread-out-the-data-is">Standard Deviation: The square root of the variance, indicating how spread out the data is.</h5>
<p>Imagine your data as a group of friends embarking on a hike. The standard deviation is like a compass, indicating how far each friend tends to stray from the group's average pace. In essence, it measures the average distance between each data point and the mean, giving you a clear picture of your data's spread and consistency.</p>
<p>Standard deviation empowers you with insights into your data's behavior, enabling you to:</p>
<ul>
<li><strong>Gauge Risk and Reward:</strong> In investing, a high standard deviation in asset returns signifies higher volatility and risk, but also the potential for higher rewards. Understanding this trade-off is crucial for building a portfolio that aligns with your financial goals.</li>
<li><strong>Predict Outcomes:</strong> In healthcare, the standard deviation of blood pressure readings can help doctors assess a patient's health risks. A larger deviation from normal values might indicate underlying health issues, prompting further investigation and proactive care.</li>
<li><strong>Optimize Processes:</strong> In manufacturing, a low standard deviation in product measurements ensures consistency and quality. Companies strive to minimize this variation to deliver reliable and satisfying products to their customers.</li>
<li><strong>Understand Natural Variation:</strong> In the natural world, standard deviation helps scientists study patterns and deviations in phenomena like weather patterns or animal behavior. This knowledge can aid in predicting future events or understanding ecological changes.</li>
</ul>
<p>Think of calculating the standard deviation as a two-step process:</p>
<ol>
<li>Calculate the variance (average squared distance from the mean).</li>
<li>Take the square root of the variance. This transforms the variance back into the original units of your data, making it easier to interpret.</li>
</ol>
<p><strong>Formula:</strong> </p>
<p>σ = √(Σ(xᵢ - μ)² / N) (for population standard deviation) </p>
<p>s = √(Σ(xᵢ - x̄)² / (n - 1)) (for sample standard deviation)</p>
<p>Where:</p>
<ul>
<li>σ (sigma) is the population standard deviation</li>
<li>s is the sample standard deviation</li>
<li>xᵢ represents each individual data point</li>
<li>μ (mu) is the population mean</li>
<li>x̄ is the sample mean</li>
<li>N is the population size</li>
<li>n is the sample size</li>
</ul>
<p><strong>Interpretation:</strong> A higher standard deviation indicates greater variability, while a lower value suggests more consistency. It provides a standardized measure of spread, allowing you to compare the variability of different datasets even if they have different units.</p>
<p><strong>Coffee Shop Service Example:</strong> Two coffee shops have the same average wait time of 5 minutes. However, Shop A has a standard deviation of 1 minute, while Shop B has a standard deviation of 3 minutes. This means that the wait times at Shop A are more consistent, typically ranging between 4 and 6 minutes, while the wait times at Shop B are more unpredictable, ranging from 2 to 8 minutes. If you value consistent service, Shop A is the clear choice.</p>
<p><strong>Practical Advice:</strong> Don't just calculate the standard deviation – use it to gain actionable insights. Combine it with other statistical measures and visualizations to fully comprehend your data's behavior. </p>
<p>Embrace standard deviation as your guide to understanding variation, making informed decisions, and driving improvements in your personal and professional endeavors.</p>
<h4 id="heading-423-measures-of-shape">4.2.3 Measures of Shape:</h4>
<h5 id="heading-skewness-a-measure-of-the-asymmetry-of-a-probability-distribution">Skewness: A measure of the asymmetry of a probability distribution.</h5>
<p>Imagine your data as a mountain range. Skewness reveals whether your mountains are perfectly symmetrical or have a longer, more gradual slope on one side. In essence, it measures the degree of asymmetry in a distribution of data. </p>
<p>A symmetrical distribution resembles a balanced scale, while a skewed one leans to one side, with a tail stretching out.</p>
<p>Skewness unlocks hidden narratives within your data, empowering you to:</p>
<ul>
<li><strong>Uncover Hidden Patterns:</strong> A positively skewed distribution, where the tail extends to the right, might indicate a few exceptionally high values. Think of income distribution, where most people earn moderate incomes, while a small number of high earners create a long right tail. Understanding this skewness can guide economic policy or marketing strategies.</li>
<li><strong>Identify Data Transformation Needs:</strong> In statistical analysis, many models assume a symmetrical distribution. If your data is skewed, transforming it (for example, taking the logarithm) can sometimes make it more suitable for these models, leading to more accurate results.</li>
<li><strong>Improve Risk Assessment:</strong> In finance, skewness is crucial for risk management. A negatively skewed distribution, with a tail to the left, suggests a higher probability of extreme negative events. This knowledge is invaluable for investors and risk managers who need to prepare for potential losses.</li>
<li><strong>Enhance Decision Making:</strong> Understanding skewness can refine your decision-making processes. For instance, if customer satisfaction ratings are positively skewed, you might focus on improving the experience of the majority rather than catering to the few outliers with extremely high scores.</li>
</ul>
<p>While the formula involves complex mathematical concepts, the essence is straightforward:</p>
<ol>
<li>Calculate the mean and standard deviation of your data.</li>
<li>Subtract the mean from each data point, cube the result, and sum up all the cubed differences.</li>
<li>Divide the sum by the cube of the standard deviation and the number of data points.</li>
</ol>
<p><strong>Formula:</strong></p>
<p>Skewness = Σ(xᵢ - μ)³ / (N * σ³)</p>
<p>Where:</p>
<ul>
<li>xᵢ represents each individual data point</li>
<li>μ (mu) is the population mean</li>
<li>σ (sigma) is the population standard deviation</li>
<li>N is the population size</li>
</ul>
<p><strong>Interpretation:</strong> Skewness is a unitless measure. A value of zero indicates perfect symmetry, positive values signify positive skewness, and negative values denote negative skewness. The larger the absolute value of the skewness, the more skewed the distribution.</p>
<p><strong>Exam Scores Example:</strong> Imagine that two classes took the same exam. Class A has a symmetrical distribution of scores, while Class B has a negatively skewed distribution. This means that in Class B, most students performed well, but a few students did poorly, pulling the mean score down. As an educator, recognizing this skewness could lead to tailored interventions to help those struggling students.</p>
<p><strong>Practical Advice:</strong> Don't let skewness intimidate you. Statistical software can easily calculate it for you. Focus on understanding what it reveals about your data. Is your data symmetrical or skewed? If skewed, which way? How does this knowledge impact your analysis and decision-making? By embracing skewness, you unlock a deeper understanding of your data's story.</p>
<h5 id="heading-kurtosis-a-measure-of-the-tailedness-of-a-probability-distribution">Kurtosis: A measure of the "tailedness" of a probability distribution.</h5>
<p>Imagine your data as a silhouette against the horizon. Kurtosis reveals whether that silhouette is sleek and slender or broad and heavy-set. Technically, it's a measure of the "tailedness" of a probability distribution – the degree to which outliers (extreme values) are present in your data. This tells you how much of the data is concentrated near the mean versus spread out in the tails.</p>
<p>Kurtosis equips you with a deeper understanding of your data's shape, enabling you to:</p>
<ul>
<li><strong>Assess Risk and Opportunity:</strong> In finance, high kurtosis in asset returns indicates a higher likelihood of extreme events, both positive and negative. This knowledge is crucial for investors seeking to balance risk and potential reward. A leptokurtic distribution, with heavy tails, suggests a higher probability of experiencing significant gains or losses compared to a normal distribution.</li>
<li><strong>Detect Anomalies:</strong> In quality control, unexpected high kurtosis might signal a deviation from normal operating conditions. This could trigger an investigation into potential manufacturing defects or process inconsistencies, allowing for timely corrective actions.</li>
<li><strong>Refine Statistical Models:</strong> Many statistical models assume a normal distribution. If your data exhibits high kurtosis, these models might not be the most accurate fit. Understanding kurtosis helps you choose appropriate models and make necessary adjustments for more reliable analysis.</li>
<li><strong>Identify Fraud or Errors:</strong> In data analysis, high kurtosis can sometimes flag fraudulent activity or data entry errors. For example, a leptokurtic distribution of transaction amounts might indicate unusual patterns that warrant further scrutiny.</li>
</ul>
<p>While the formula delves into higher-order moments, the concept is relatively straightforward:</p>
<ol>
<li>Calculate the mean and standard deviation of your data.</li>
<li>Subtract the mean from each data point, raise the result to the fourth power, and sum up all these values.</li>
<li>Divide the sum by the fourth power of the standard deviation and the number of data points.</li>
</ol>
<p><strong>Formula:</strong> </p>
<p>Kurtosis = Σ(xᵢ - μ)⁴ / (N * σ⁴)</p>
<p>Where:</p>
<ul>
<li>xᵢ represents each individual data point</li>
<li>μ (mu) is the population mean</li>
<li>σ (sigma) is the population standard deviation</li>
<li>N is the population size</li>
</ul>
<p><strong>Interpretation:</strong> A normal distribution has a kurtosis of 3.</p>
<ul>
<li><strong>Mesokurtic (Kurtosis ≈ 3):</strong> The distribution has tails similar to a normal distribution.</li>
<li><strong>Leptokurtic (Kurtosis &gt; 3):</strong> The distribution has heavier tails and a sharper peak than a normal distribution.</li>
<li><strong>Platykurtic (Kurtosis &lt; 3):</strong> The distribution has lighter tails and a flatter peak than a normal distribution.</li>
</ul>
<p><strong>Stock Market Volatility Example:</strong> Consider two stocks with similar average returns. Stock A has a leptokurtic distribution of returns, while Stock B has a mesokurtic distribution. This means that Stock A is more likely to experience extreme price swings, both upwards and downwards, compared to Stock B. If you're a risk-averse investor, you might prefer Stock B with its more predictable returns.</p>
<p><strong>Practical Advice:</strong> Don't be overwhelmed by the technicalities of kurtosis. Statistical software readily calculates it for you. Focus on the insights it provides. What does the shape of your data's tails reveal about potential risks, opportunities, or the need for alternative models? </p>
<p>By understanding kurtosis, you gain a valuable tool for making informed decisions and navigating the complexities of data analysis.</p>
<h4 id="heading-424-frequency-distribution">4.2.4 Frequency Distribution:</h4>
<p>Imagine your data as a diverse group of individuals with varying interests. A frequency distribution reveals which interests are most common, offering insights into the preferences and trends within the group. In essence, it's a summary of how often each unique value appears in your dataset. Think of it as a tally chart or a popularity ranking for your data points.</p>
<p>Frequency distribution is your backstage pass to understanding your data's composition:</p>
<ul>
<li><strong>Uncover Common Ground:</strong> In market research, frequency distributions reveal the most popular products or services, guiding companies in tailoring their offerings to meet customer demand.</li>
<li><strong>Identify Patterns:</strong> In healthcare, tracking the frequency of different symptoms can help doctors diagnose illnesses. A high frequency of fever and cough, for instance, might suggest a respiratory infection.</li>
<li><strong>Spot Anomalies:</strong> In finance, analyzing the frequency of transaction amounts can help detect fraud. An unusually high frequency of round-number transactions could be a red flag for suspicious activity.</li>
<li><strong>Make Informed Decisions:</strong> In education, understanding the frequency distribution of student grades can inform instructional strategies. If a large number of students struggle with a particular concept, the teacher might need to revisit it with a different approach.</li>
</ul>
<p>Creating a frequency distribution is simple:</p>
<ol>
<li>Identify all the unique values in your dataset.</li>
<li>Count how many times each value appears.</li>
<li>Organize this information in a table or chart, with values listed alongside their corresponding frequencies.</li>
</ol>
<p><strong>Interpretation:</strong> A frequency distribution tells you at a glance which values are most prevalent in your data. The higher the frequency, the more common or popular that value is. Pay attention to:</p>
<ul>
<li><strong>Mode:</strong> The value with the highest frequency is the mode, representing the most common or typical value in your dataset.</li>
<li><strong>Spread:</strong> The distribution of frequencies gives you a sense of how varied your data is. A wide range of frequencies indicates greater diversity, while a narrow range suggests more uniformity.</li>
</ul>
<p><strong>Customer Feedback Example:</strong> Imagine you own a restaurant and collect feedback from your customers using a 5-star rating system. Your frequency distribution might look like this:</p>
<ul>
<li>1 Star: 5 reviews</li>
<li>2 Stars: 10 reviews</li>
<li>3 Stars: 25 reviews</li>
<li>4 Stars: 30 reviews</li>
<li>5 Stars: 20 reviews</li>
</ul>
<p>This tells you that most of your customers are satisfied, with the majority giving you 3 or 4 stars. However, there's room for improvement, as a significant number of customers gave you only 1 or 2 stars. This information can help you identify areas where you need to enhance your service.</p>
<p><strong>Practical Advice:</strong> Don't underestimate the power of frequency distribution. It's a simple yet powerful tool that can uncover valuable insights, helping you make data-driven decisions and gain a competitive edge. </p>
<p>Whether you're analyzing customer data, financial information, or scientific measurements, frequency distribution provides a clear picture of your data's composition and reveals the patterns that matter most.</p>
<h4 id="heading-425-percentiles">4.2.5 Percentiles:</h4>
<p>Imagine your data as a race with 100 runners. Percentiles are the finish lines that divide the runners into 100 equal groups. Each percentile represents the percentage of values in the dataset that fall below a particular value. For example, if you score in the 90th percentile on a test, you performed better than 90% of test-takers.</p>
<p>Percentiles provide valuable insights into relative standing and performance:</p>
<ul>
<li><strong>Benchmarking:</strong> Standardized tests often report scores in percentiles, allowing students to compare their performance to others nationwide. This helps identify areas of strength and weakness.</li>
<li><strong>Growth Tracking:</strong> Monitoring changes in percentile scores over time can reveal individual or group progress. For example, a student whose math percentile increases from the 60th to the 80th percentile has shown significant improvement.</li>
<li><strong>Identifying Outliers:</strong> Extreme percentiles (for example, the 99th percentile) can help identify outliers – individuals or data points that are exceptionally high or low compared to the rest of the group.</li>
<li><strong>Setting Standards:</strong> Percentiles can be used to establish benchmarks or thresholds for performance. For example, a company might set a goal for its sales team to reach the 75th percentile in revenue generation.</li>
</ul>
<p>Calculating percentiles involves several steps:</p>
<ol>
<li>Order the data from smallest to largest.</li>
<li>Calculate the rank of the percentile you want to find (for example, for the 25th percentile, the rank is 25).</li>
<li>Determine the index of the value corresponding to that rank using a specific formula.</li>
<li>If the index is a whole number, the percentile is the value at that index. If the index is a fraction, the percentile is the average of the values at the two closest indices.</li>
</ol>
<p><strong>Interpretation:</strong> A percentile tells you the percentage of values in the dataset that fall below a given value. For example, if your income is in the 80th percentile, it means you earn more than 80% of the people in your reference group. The higher the percentile, the better the relative performance or standing.</p>
<p><strong>Infant Growth Example:</strong> Pediatricians often use growth charts that plot percentiles for weight and height based on age and gender. If a baby's weight is at the 50th percentile, it means they weigh more than 50% of babies their age and gender. This helps parents and doctors track the child's growth and development compared to their peers.</p>
<p><strong>Practical Advice:</strong> Don't just focus on your percentile – consider the context and distribution of the data. A high percentile in one group might not be as impressive in another group with a higher overall performance. Use percentiles as a tool to understand relative standing, track progress, and set goals.</p>
<h4 id="heading-426-quartiles">4.2.6 Quartiles</h4>
<p>Imagine your data as a map, charted from lowest to highest values. Quartiles are like compass points that divide your map into four equal territories, each representing 25% of your data. They're specific percentiles: Q1 (25th percentile), Q2 (50th percentile, also the median), and Q3 (75th percentile).</p>
<p>Quartiles give you a more granular view of your data's distribution than just the median alone:</p>
<ul>
<li><strong>Segmenting Your Audience:</strong> In marketing, quartiles can help you divide your customer base into distinct segments based on spending habits or engagement levels. This enables targeted campaigns that resonate with each group's unique characteristics.</li>
<li><strong>Evaluating Performance:</strong> In education, quartiles can be used to assess student performance on standardized tests. A student in the top quartile (Q4) performed better than 75% of their peers, while a student in the bottom quartile (Q1) scored lower than 75%. This information can inform personalized learning plans.</li>
<li><strong>Identifying Outliers and Skewness:</strong> Quartiles can help you pinpoint outliers—values that fall far outside the interquartile range (IQR), the range between Q1 and Q3. They also provide clues about the skewness of your data. A larger gap between Q3 and the maximum value than between Q1 and the minimum value suggests positive skewness.</li>
<li><strong>Data Visualization:</strong> Quartiles are the building blocks of box plots, a powerful visualization tool that succinctly summarizes a dataset's distribution, highlighting its central tendency, spread, and potential outliers.</li>
</ul>
<p>Finding quartiles involves sorting your data and identifying specific percentiles:</p>
<ol>
<li>Order your data from smallest to largest.</li>
<li>Identify the median (Q2), which divides the data in half.</li>
<li>The median of the lower half of the data is Q1.</li>
<li>The median of the upper half of the data is Q3.</li>
</ol>
<p>Quartiles provide valuable insights into your data's structure:</p>
<ul>
<li><strong>Q1:</strong> The value below which 25% of the data falls.</li>
<li><strong>Q2 (Median):</strong> The value that splits the data in half, with 50% falling below and 50% above.</li>
<li><strong>Q3:</strong> The value below which 75% of the data falls.</li>
<li><strong>Interquartile Range (IQR):</strong> The range between Q1 and Q3, representing the middle 50% of the data. A large IQR indicates greater variability, while a small IQR suggests more consistency.</li>
</ul>
<p><strong>Employee Salaries Example:</strong> Imagine analyzing salaries at a company. Q1 might be $40,000, Q2 (median) might be $50,000, and Q3 might be $65,000. This tells you that 25% of employees earn less than $40,000, 50% earn less than $50,000, and 75% earn less than $65,000. The IQR of $25,000 indicates a moderate spread in salaries.</p>
<p><strong>Practical Advice:</strong></p>
<p>Quartiles are a valuable tool for understanding the distribution of your data. Combine them with other descriptive statistics and visualizations (like histograms and box plots) to gain a comprehensive picture of your data's central tendency, spread, and potential outliers. Remember, quartiles are your compass points for navigating the landscape of your data, guiding you towards actionable insights.</p>
<h4 id="heading-427-box-plot-box-and-whisker-plot">4.2.7 Box Plot (Box and Whisker Plot):</h4>
<p>Imagine your data as a story with characters spread across different scenes. A box plot is like a movie trailer, summarizing the key plot points – the central action and the dramatic outliers. Technically, it's a visual representation of a dataset's distribution using five key numbers: the minimum, first quartile (Q1), median (Q2), third quartile (Q3), and maximum.</p>
<p>Box plots provide a concise yet powerful summary of your data's essential features:</p>
<ul>
<li><strong>Spotting Outliers at a Glance:</strong> The "whiskers" extending from the box instantly reveal potential outliers, those data points far removed from the central action. This visual cue alerts you to unusual values that might warrant further investigation or special consideration.</li>
<li><strong>Comparing Groups Side-by-Side:</strong> Box plots excel at comparing distributions across multiple groups. By aligning box plots side by side, you can quickly assess differences in central tendency, spread, and symmetry between groups. This is invaluable for market segmentation, performance evaluation, or experimental analysis.</li>
<li><strong>Unveiling Skewness and Symmetry:</strong> The relative position of the median within the box and the length of the whiskers provide clues about your data's skewness. A longer upper whisker suggests positive skew, while a longer lower whisker indicates negative skew. A symmetrical box plot points to a balanced distribution.</li>
<li><strong>Understanding Variability:</strong> The length of the box (the interquartile range, or IQR) represents the spread of the middle 50% of your data. A longer box signifies greater variability, while a shorter box indicates more consistent data.</li>
</ul>
<p>Creating a box plot involves sorting your data and identifying key percentiles:</p>
<ol>
<li>Order your data from smallest to largest.</li>
<li>Identify the median (Q2), which marks the center of the box.</li>
<li>Find Q1 and Q3, the medians of the lower and upper halves of the data. These mark the ends of the box.</li>
<li>Calculate the IQR (Q3 - Q1).</li>
<li>Draw whiskers extending from the box to the minimum and maximum values (or to a calculated fence to identify outliers).</li>
</ol>
<p>A box plot tells a visual story about your data:</p>
<ul>
<li><strong>Central Tendency:</strong> The line inside the box represents the median, the value that splits the data in half.</li>
<li><strong>Spread:</strong> The length of the box (IQR) shows the spread of the middle 50% of the data.</li>
<li><strong>Symmetry:</strong> The position of the median within the box and the relative lengths of the whiskers reveal the symmetry or skewness of the distribution.</li>
<li><strong>Outliers:</strong> Data points beyond the whiskers are potential outliers.</li>
</ul>
<p><strong>Real Estate Prices Example:</strong> Imagine comparing housing prices in two neighborhoods. A box plot can quickly reveal that one neighborhood has a higher median price but also a wider range of prices, indicating greater variability in housing options. This visual comparison allows potential buyers to quickly grasp the key differences between the two markets.</p>
<p><strong>Practical Advice:</strong> Don't just view a box plot – engage with it. Ask yourself questions: What's the story your data is telling? Are there outliers? Is the distribution skewed? How do different groups compare? By interacting with the box plot, you unlock its full potential for understanding your data and making informed decisions.</p>
<h4 id="heading-428-outliers">4.2.8 Outliers:</h4>
<p>Imagine your data as a flock of birds flying in formation. Outliers are the mavericks – those birds that stray significantly from the group, soaring higher or dipping lower than the rest. </p>
<p>In statistical terms, outliers are data points that differ substantially from the majority of observations in your dataset. They stand out, defying the norms and challenging your assumptions.</p>
<p><strong>Purpose and Use:</strong> Outliers are not just anomalies – they are valuable clues that can unlock hidden truths within your data:</p>
<ul>
<li><strong>Data Quality Assurance:</strong> In data collection and entry, outliers often signal errors or inconsistencies. Identifying and correcting these outliers can significantly improve the accuracy and reliability of your analysis.</li>
<li><strong>Uncovering Anomalies:</strong> In fraud detection, outliers can be red flags for suspicious activity. For instance, an unusually large transaction in a customer's spending pattern might warrant further investigation.</li>
<li><strong>Driving Innovation:</strong> In scientific research, outliers can sometimes lead to groundbreaking discoveries. A data point that defies expectations might point to a new phenomenon or challenge existing theories, sparking further exploration and innovation.</li>
<li><strong>Segmenting Your Audience:</strong> In marketing, identifying outliers in customer behavior can help you discover niche markets or unique customer segments with specific needs and preferences.</li>
<li><strong>Refining Models:</strong> In statistical modeling, outliers can unduly influence the model's parameters. Identifying and addressing outliers can lead to more accurate and robust models that better represent the underlying patterns in your data.</li>
</ul>
<p>There are several methods for identifying outliers:</p>
<ul>
<li><strong>Z-Score:</strong> Calculate how many standard deviations a data point is from the mean. A z-score greater than 3 or less than -3 often indicates an outlier.</li>
<li><strong>Interquartile Range (IQR):</strong> Outliers are defined as values that fall below Q1 - 1.5 <em> IQR or above Q3 + 1.5 </em> IQR.</li>
<li><strong>Visual Inspection:</strong> Box plots and scatter plots can visually highlight outliers.</li>
</ul>
<p>An outlier is not inherently good or bad. Its significance depends on the context and your research question:</p>
<ul>
<li><strong>Error:</strong> If an outlier is likely due to a measurement error or data entry mistake, it should be corrected or removed from the dataset.</li>
<li><strong>Genuine Anomaly:</strong> If an outlier represents a genuine but rare occurrence, it should be carefully analyzed to understand its implications. It might be a valuable insight or a unique case that warrants special attention.</li>
</ul>
<p><strong>Website Traffic Example:</strong> Imagine analyzing website traffic data. You notice a sudden spike in traffic on a particular day. This could be an outlier caused by a technical glitch or a genuine surge in interest due to a viral social media post. Investigating the cause of this outlier can help you understand your audience better and optimize your website's performance.</p>
<p><strong>Practical Advice:</strong> Don't be afraid of outliers. Embrace them as potential sources of valuable information. Carefully investigate their causes and consider their implications for your analysis. Remember, outliers can be your data's most interesting and insightful characters, revealing hidden truths and sparking new discoveries.</p>
<h4 id="heading-429-correlation">4.2.9 Correlation:</h4>
<p>Imagine your data as pairs of dancers on a ballroom floor. Correlation reveals how gracefully those pairs move together. Are they in perfect sync, mirroring each other's steps (positive correlation)? Are they moving in opposite directions, creating a dynamic tension (negative correlation)? Or are their movements independent, with no discernible pattern (no correlation)? </p>
<p>In statistical terms, correlation quantifies the strength and direction of a linear relationship between two variables.</p>
<p>Correlation unlocks the hidden connections within your data, enabling you to:</p>
<ul>
<li><strong>Uncover Hidden Relationships:</strong> In healthcare, a strong positive correlation between smoking and lung cancer risk revealed the dire consequences of tobacco use, leading to public health campaigns and policy changes.</li>
<li><strong>Make Predictions:</strong> In finance, correlation helps investors build diversified portfolios. By choosing assets with low or negative correlations, they can reduce overall risk. For instance, if stocks and bonds typically move in opposite directions, a diversified portfolio can buffer against market fluctuations.</li>
<li><strong>Test Hypotheses:</strong> In scientific research, correlation is used to test theories. For example, a study might examine the correlation between exercise and stress levels to assess the potential benefits of physical activity on mental health.</li>
<li><strong>Optimize Marketing:</strong> In business, analyzing correlations between customer demographics and purchasing behavior can help companies tailor their marketing strategies to specific target audiences. For instance, a positive correlation between income and luxury product purchases might prompt a company to focus advertising efforts on high-income consumers.</li>
</ul>
<p>The most common measure of correlation is the Pearson correlation coefficient (r). It's calculated by:</p>
<ol>
<li>Standardizing both variables (subtracting the mean and dividing by the standard deviation).</li>
<li>Multiplying the standardized values for each pair of data points.</li>
<li>Summing up these products and dividing by the number of data points minus one.</li>
</ol>
<p><strong>Formula:</strong></p>
<p>r = Σ((xᵢ - x̄) / sₓ) * ((yᵢ - ȳ) / sᵧ) / (n - 1)</p>
<p>Where:</p>
<ul>
<li>xᵢ and yᵢ represent individual data points for each variable</li>
<li>x̄ and ȳ are the means of the respective variables</li>
<li>sₓ and sᵧ are the standard deviations of the respective variables</li>
<li>n is the number of data points</li>
</ul>
<p><strong>Interpretation:</strong> The correlation coefficient (r) ranges from -1 to 1:</p>
<ul>
<li>r = 1: Perfect positive linear correlation (as one variable increases, the other increases proportionally).</li>
<li>r = -1: Perfect negative linear correlation (as one variable increases, the other decreases proportionally).</li>
<li>r = 0: No linear correlation (the variables are not linearly related).</li>
</ul>
<p><strong>Ice Cream Sales and Temperature Example:</strong> You might observe a strong positive correlation between ice cream sales and temperature. As the temperature rises, so do ice cream sales. This information can be used by ice cream vendors to plan inventory and staffing levels, ensuring they are well-prepared for hot weather.</p>
<p><strong>Practical Advice:</strong> Don't assume causation from correlation. A strong correlation between two variables doesn't necessarily mean that one causes the other. There might be other underlying factors at play. </p>
<p>Always consider alternative explanations and use correlation as a starting point for further investigation. Combine it with other statistical tools and domain knowledge to gain a deeper understanding of the relationships within your data.</p>
<h3 id="heading-43-data-cleaning-and-preparation">4.3 Data Cleaning and Preparation</h3>
<p>Data integrity is paramount for deriving meaningful insights and making informed decisions. Raw data often contains imperfections that can skew analyses and lead to erroneous conclusions. </p>
<p> Addressing these common challenges—missing values, duplicates, and outliers—is a critical step in ensuring the reliability and accuracy of your data-driven initiatives.</p>
<h4 id="heading-missing-values-bridging-the-information-gap">Missing Values: Bridging the Information Gap</h4>
<p>Missing values, akin to gaps in a puzzle, can compromise the completeness of your dataset. Implementing effective strategies is crucial:</p>
<ul>
<li><strong>Deletion:</strong> When missing data is minimal and occurs randomly, deleting rows or columns containing missing values can be viable. But this approach should be used judiciously, as it can reduce sample size and potentially introduce bias.</li>
<li><strong>Imputation:</strong> A more sophisticated approach involves replacing missing values with plausible estimates. For numerical data, imputation techniques such as mean, median, or mode substitution can be employed. For more complex scenarios, regression imputation or multiple imputation methods may be warranted.</li>
<li><strong>Expert Consultation:</strong> In cases where missing data arises due to specific reasons, consulting domain experts can offer valuable insights to inform the imputation process.</li>
</ul>
<h4 id="heading-duplicates-ensuring-data-uniqueness">Duplicates: Ensuring Data Uniqueness</h4>
<p>Duplicate data points, akin to redundant information, can distort statistical analyses and lead to erroneous interpretations. Resolving duplicates is essential:</p>
<ul>
<li><strong>Identification:</strong> Utilize software tools to identify duplicate records based on specific criteria, such as exact or fuzzy matches.</li>
<li><strong>Resolution:</strong> Implement a systematic approach to resolve duplicates. Options include retaining the first or last occurrence, averaging duplicate values, or removing all instances of duplication.</li>
<li><strong>Prevention:</strong> Establish data validation protocols and deduplication procedures during data collection and entry to minimize the occurrence of duplicates in the future.</li>
</ul>
<h4 id="heading-outliers-navigating-data-anomalies">Outliers: Navigating Data Anomalies</h4>
<p>Outliers, data points that significantly deviate from the norm, can either be valuable anomalies or disruptive errors. A strategic approach is required:</p>
<ul>
<li><strong>Investigation:</strong> Thoroughly investigate the cause of outliers. Are they legitimate extreme values, measurement errors, or data entry mistakes? Understanding their origin is crucial for determining the appropriate course of action.</li>
<li><strong>Transformation:</strong> In cases where genuine outliers distort analysis, consider data transformation techniques, such as logarithmic or square root transformations, to mitigate their impact while preserving their informational value.</li>
<li><strong>Robust Methods:</strong> Employ statistical methods that are less sensitive to outliers, such as the median or trimmed mean, to obtain more representative measures of central tendency.</li>
<li><strong>Sensitivity Analysis:</strong> Assess the influence of outliers on your results by conducting sensitivity analyses with and without these data points. This allows for a comprehensive evaluation of their impact and facilitates transparent reporting.</li>
</ul>
<p>By diligently addressing missing values, duplicates, and outliers, you fortify the integrity of your data, ensuring that subsequent analyses and interpretations are robust and reliable.</p>
<h3 id="heading-44-exploratory-data-analysis-eda">4.4 Exploratory Data Analysis (EDA)</h3>
<p>Imagine yourself as an architect tasked with designing a magnificent skyscraper. Before the first brick is laid, you meticulously examine blueprints, assess the terrain, and envision the final masterpiece. </p>
<p>Similarly, in the realm of data science, Exploratory Data Analysis (EDA) serves as the blueprint for your analytical journey. It's a systematic investigation that uncovers hidden patterns, ensuring data integrity, and laying the groundwork for accurate, actionable insights.</p>
<h4 id="heading-why-eda-matters">Why EDA Matters:</h4>
<p>Exploratory Data Analysis (EDA) is a critical phase in any data-driven project, serving as the bedrock upon which sound analysis and decision-making are built. Going beyond mere data preparation, EDA empowers analysts to unlock the full potential of their datasets and navigate the complexities of the analytical process with confidence.</p>
<h5 id="heading-uncover-actionable-insights">Uncover Actionable Insights:</h5>
<p>EDA is a journey of discovery, unveiling hidden patterns, correlations, and anomalies that can transform your understanding of the data. By meticulously exploring each variable and their interactions, you can:</p>
<ul>
<li><strong>Identify critical trends and relationships:</strong> Discover subtle patterns that might not be apparent at first glance, revealing valuable insights that can drive strategic decisions.</li>
<li><strong>Detect emerging opportunities or risks:</strong> Uncover shifts in customer behavior, market dynamics, or operational performance, enabling proactive responses and mitigating potential threats.</li>
<li><strong>Pinpoint anomalies and data quality issues:</strong> Identify outliers, inconsistencies, or errors in your data, ensuring the accuracy and reliability of your analysis.</li>
</ul>
<h5 id="heading-optimize-analytical-strategies">Optimize Analytical Strategies:</h5>
<p>EDA provides the foundation for making informed decisions throughout the analytical process:</p>
<ul>
<li><strong>Select appropriate statistical methods:</strong> Understand your data's distribution, relationships, and characteristics to choose the right statistical tools and models, maximizing the validity and reliability of your results.</li>
<li><strong>Refine feature selection:</strong> Identify the most relevant variables that drive the outcomes you are investigating, leading to more efficient and targeted analysis.</li>
<li><strong>Enhance interpretation:</strong> Develop a comprehensive understanding of your data's nuances and limitations, ensuring accurate interpretations and actionable recommendations.</li>
</ul>
<h5 id="heading-ensure-data-integrity-and-reliability">Ensure Data Integrity and Reliability:</h5>
<p>EDA is essential for establishing data quality, a cornerstone of sound analysis:</p>
<ul>
<li><strong>Address missing values:</strong> Identify and handle missing data appropriately, preventing bias and maintaining data integrity.</li>
<li><strong>Resolve duplicates:</strong> Ensure the uniqueness of data points, avoiding overrepresentation and potential skewing of results.</li>
<li><strong>Correct errors:</strong> Identify and rectify errors in data entry, measurement, or coding to ensure the accuracy and reliability of your findings.</li>
<li><strong>Manage outliers:</strong> Investigate and address outliers, whether they are legitimate extreme values or errors, to improve the robustness of your analysis.</li>
</ul>
<h5 id="heading-foster-curiosity-and-innovation">Foster Curiosity and Innovation:</h5>
<p>Beyond its practical applications, EDA cultivates a culture of curiosity and innovation. By delving into your data, you may stumble upon unexpected patterns, intriguing correlations, or perplexing anomalies. </p>
<p>These discoveries can spark new questions, challenge existing assumptions, and drive the pursuit of deeper insights.</p>
<p>In essence, EDA is not merely a preliminary step – it's a continuous process of discovery that fuels data-driven decision-making, fosters innovation, and ultimately leads to more meaningful and impactful outcomes.</p>
<h4 id="heading-the-eda-toolkit-your-arsenal-for-data-exploration">The EDA Toolkit: Your Arsenal for Data Exploration</h4>
<p>Exploratory Data Analysis (EDA) equips analysts with a robust suite of methodologies designed to facilitate a deep understanding of their datasets. These tools enable the identification of underlying patterns, relationships, and anomalies, laying the groundwork for accurate and insightful analysis.</p>
<h5 id="heading-summary-statistics">Summary Statistics:</h5>
<p>Through descriptive measures like mean, median, standard deviation, and quartiles, analysts gain a concise overview of their data's central tendency, dispersion, and distribution. </p>
<p>These summary statistics provide a quantitative snapshot of the data's key characteristics, serving as a valuable starting point for further exploration.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Sample data</span>
data = {<span class="hljs-string">'Sales'</span>: [<span class="hljs-number">1200</span>, <span class="hljs-number">1500</span>, <span class="hljs-number">1350</span>, <span class="hljs-number">2000</span>, <span class="hljs-number">800</span>, <span class="hljs-number">2200</span>, <span class="hljs-number">1700</span>, <span class="hljs-number">1950</span>]}
df = pd.DataFrame(data)

<span class="hljs-comment"># Calculate and display summary statistics</span>
summary = df.describe()
print(summary)
</code></pre>
<p><strong>Explanation:</strong> This code calculates and displays key summary statistics for the 'Sales' column, including mean, standard deviation, minimum, maximum, and quartiles.</p>
<h5 id="heading-visualization">Visualization:</h5>
<p>The power of data visualization lies in its ability to transform complex numerical data into intuitive graphical representations. Utilizing a diverse range of charts and graphs, such as histograms, scatter plots, box plots, and heatmaps, analysts can uncover hidden patterns and trends that might not be readily apparent in raw data. </p>
<p>Each visualization technique offers a unique perspective, allowing you to explore relationships between variables, identify outliers, and understand the overall distribution of the data.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Create a histogram to visualize the distribution of sales</span>
plt.hist(df[<span class="hljs-string">'Sales'</span>], bins=<span class="hljs-number">8</span>, color=<span class="hljs-string">'skyblue'</span>, edgecolor=<span class="hljs-string">'black'</span>)
plt.title(<span class="hljs-string">'Distribution of Sales'</span>)
plt.xlabel(<span class="hljs-string">'Sales'</span>)
plt.ylabel(<span class="hljs-string">'Frequency'</span>)
plt.show()
</code></pre>
<p><strong>Explanation:</strong> The code generates a histogram that visually represents the distribution of 'Sales' data, showing the frequency of different sales amounts.</p>
<h5 id="heading-data-transformation">Data Transformation:</h5>
<p>Data transformation techniques, including logarithmic and square root transformations, are employed to address issues such as skewness and outliers, thereby enhancing the suitability of the data for subsequent analysis. </p>
<p>By normalizing the data's distribution and mitigating the impact of extreme values, these transformations ensure the robustness and validity of statistical models and analytical techniques.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Apply a square root transformation to 'Sales'</span>
df[<span class="hljs-string">'Sqrt_Sales'</span>] = np.sqrt(df[<span class="hljs-string">'Sales'</span>])

<span class="hljs-comment"># Display summary statistics of transformed data</span>
print(df[<span class="hljs-string">'Sqrt_Sales'</span>].describe())
</code></pre>
<p><strong>Explanation:</strong> A square root transformation is applied to the 'Sales' column, and summary statistics of this transformed data are displayed, which helps in handling skewed data.</p>
<h5 id="heading-data-cleaning">Data Cleaning:</h5>
<p>Data cleaning is a fundamental aspect of EDA, encompassing the identification and remediation of errors, missing values, and duplicates. </p>
<p>By meticulously cleaning the data, you can ensure its accuracy and completeness, establishing a solid foundation for reliable analysis and informed decision-making.</p>
<pre><code class="lang-python"><span class="hljs-comment"># Create data with missing values and duplicates</span>
data = {<span class="hljs-string">'Product'</span>: [<span class="hljs-string">'A'</span>, <span class="hljs-string">'B'</span>, <span class="hljs-string">'A'</span>, <span class="hljs-string">'C'</span>, <span class="hljs-string">'B'</span>, np.nan, <span class="hljs-string">'D'</span>, <span class="hljs-string">'D'</span>],
        <span class="hljs-string">'Price'</span>: [<span class="hljs-number">25</span>, <span class="hljs-number">30</span>, <span class="hljs-number">25</span>, <span class="hljs-number">35</span>, <span class="hljs-number">30</span>, <span class="hljs-number">40</span>, <span class="hljs-number">45</span>, <span class="hljs-number">45</span>]}
df = pd.DataFrame(data)

<span class="hljs-comment"># Drop duplicates based on both columns</span>
df.drop_duplicates(inplace=<span class="hljs-literal">True</span>)

<span class="hljs-comment"># Fill missing values with the most frequent value (mode) in 'Product' column</span>
df[<span class="hljs-string">'Product'</span>].fillna(df[<span class="hljs-string">'Product'</span>].mode()[<span class="hljs-number">0</span>], inplace=<span class="hljs-literal">True</span>)

print(df)
</code></pre>
<p><strong>Explanation:</strong> The code creates a dataframe with missing values and duplicates. It then cleans the data by removing duplicates and filling in missing values in the 'Product' column with the most frequent value (the mode).</p>
<h5 id="heading-histograms">Histograms:</h5>
<p>Imagine a bar chart that reveals the popularity contest of your numerical data. Each bar represents a range of values (for example, ages 20-29, 30-39), and its height indicates how many data points fall within that range.  </p>
<p>A histogram quickly shows you the most common values, the overall shape of the distribution (symmetrical, skewed), and potential outliers.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Sample data (replace with your own data)</span>
data = np.random.normal(<span class="hljs-number">50</span>, <span class="hljs-number">15</span>, <span class="hljs-number">1000</span>)  <span class="hljs-comment"># Generate 1000 data points from a normal distribution</span>

<span class="hljs-comment"># Create histogram</span>
plt.hist(data, bins=<span class="hljs-number">10</span>, color=<span class="hljs-string">'skyblue'</span>, alpha=<span class="hljs-number">0.7</span>, edgecolor=<span class="hljs-string">'black'</span>)
plt.title(<span class="hljs-string">'Distribution of Data'</span>)
plt.xlabel(<span class="hljs-string">'Value'</span>)
plt.ylabel(<span class="hljs-string">'Frequency'</span>)
plt.show()
</code></pre>
<h5 id="heading-bar-charts">Bar Charts:</h5>
<p>This go-to chart for categorical data is like a visual ballot box. Each bar represents a distinct category (for example, product types, customer demographics), and its height reveals the frequency or proportion of data points within that category. </p>
<p>Bar charts instantly showcase the most and least popular categories, making them ideal for quick comparisons and identifying dominant trends.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Sample data (replace with your own categories and frequencies)</span>
categories = [<span class="hljs-string">'Category A'</span>, <span class="hljs-string">'Category B'</span>, <span class="hljs-string">'Category C'</span>, <span class="hljs-string">'Category D'</span>]
frequencies = [<span class="hljs-number">25</span>, <span class="hljs-number">40</span>, <span class="hljs-number">15</span>, <span class="hljs-number">20</span>]

<span class="hljs-comment"># Create bar chart</span>
plt.bar(categories, frequencies, color=[<span class="hljs-string">'lightblue'</span>, <span class="hljs-string">'lightcoral'</span>, <span class="hljs-string">'lightgreen'</span>, <span class="hljs-string">'gold'</span>])
plt.title(<span class="hljs-string">'Distribution of Categories'</span>)
plt.xlabel(<span class="hljs-string">'Category'</span>)
plt.ylabel(<span class="hljs-string">'Frequency'</span>)
plt.show()
</code></pre>
<h5 id="heading-scatter-plots">Scatter Plots:</h5>
<p>Picture a field of dots, each representing a pair of values from two different variables (for example, advertising spending and sales revenue). The scatter plot reveals the relationship between these variables.  </p>
<p>A cluster of dots sloping upwards suggests a positive correlation (when one increases, so does the other), while a downward slope indicates a negative correlation. A scattered field of dots means little or no relationship.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt

<span class="hljs-comment"># Sample data (replace with your own x and y values)</span>
x = [<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>]
y = [<span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">4</span>, <span class="hljs-number">7</span>, <span class="hljs-number">6</span>]

<span class="hljs-comment"># Create scatter plot</span>
plt.scatter(x, y, color=<span class="hljs-string">'purple'</span>, marker=<span class="hljs-string">'o'</span>)
plt.title(<span class="hljs-string">'Relationship Between X and Y'</span>)
plt.xlabel(<span class="hljs-string">'X'</span>)
plt.ylabel(<span class="hljs-string">'Y'</span>)
plt.show()
</code></pre>
<h5 id="heading-box-plots">Box Plots:</h5>
<p>This five-number summary is like a miniature story of your data. The "box" encompasses the middle 50% of your data (from the 25th to 75th percentile), with a line marking the median (50th percentile). The "whiskers" extend to the minimum and maximum values (or a calculated fence to show outliers). </p>
<p>Box plots are perfect for comparing distributions across multiple groups, revealing differences in central tendency, spread, and symmetry.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns

<span class="hljs-comment"># Sample data (replace with your own data for each group)</span>
data = {<span class="hljs-string">'Group A'</span>: [<span class="hljs-number">10</span>, <span class="hljs-number">15</span>, <span class="hljs-number">20</span>, <span class="hljs-number">25</span>, <span class="hljs-number">30</span>, <span class="hljs-number">40</span>, <span class="hljs-number">50</span>],
        <span class="hljs-string">'Group B'</span>: [<span class="hljs-number">5</span>, <span class="hljs-number">12</span>, <span class="hljs-number">18</span>, <span class="hljs-number">22</span>, <span class="hljs-number">28</span>, <span class="hljs-number">35</span>, <span class="hljs-number">42</span>]}
df = pd.DataFrame(data)

<span class="hljs-comment"># Create box plot</span>
sns.boxplot(data=df)
plt.title(<span class="hljs-string">'Comparison of Group A and Group B'</span>)
plt.ylabel(<span class="hljs-string">'Value'</span>)
plt.show()
</code></pre>
<h5 id="heading-heatmaps">Heatmaps:</h5>
<p>Think of a heatmap as a visual thermometer for correlations. It displays a matrix where each cell represents the correlation between two variables. The color intensity of each cell indicates the strength of the correlation, ranging from cool blues (negative correlation) to fiery reds (positive correlation). </p>
<p>Heatmaps are excellent for identifying patterns and relationships within a large number of variables.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Sample data (replace with your own dataset)</span>
data = {<span class="hljs-string">'Math'</span>: np.random.randint(<span class="hljs-number">50</span>, <span class="hljs-number">100</span>, <span class="hljs-number">100</span>),
        <span class="hljs-string">'Science'</span>: np.random.randint(<span class="hljs-number">60</span>, <span class="hljs-number">95</span>, <span class="hljs-number">100</span>),
        <span class="hljs-string">'English'</span>: np.random.randint(<span class="hljs-number">70</span>, <span class="hljs-number">90</span>, <span class="hljs-number">100</span>)}
df = pd.DataFrame(data)

<span class="hljs-comment"># Calculate correlation matrix</span>
corr_matrix = df.corr()

<span class="hljs-comment"># Create heatmap</span>
sns.heatmap(corr_matrix, annot=<span class="hljs-literal">True</span>, cmap=<span class="hljs-string">"coolwarm"</span>, fmt=<span class="hljs-string">".2f"</span>)
plt.title(<span class="hljs-string">'Correlation Heatmap'</span>)
plt.show()
</code></pre>
<h5 id="heading-correlation-matrix">Correlation Matrix:</h5>
<p>This numerical counterpart to the heatmap quantifies the linear relationship between pairs of variables. Each cell contains a correlation coefficient (r) ranging from -1 (perfect negative correlation) to 1 (perfect positive correlation). </p>
<p>Correlation matrices provide a concise way to assess the strength and direction of relationships between multiple variables, guiding you towards potentially meaningful associations for further analysis.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Sample data (same as above)</span>

<span class="hljs-comment"># Calculate and print correlation matrix</span>
corr_matrix = df.corr()
print(corr_matrix)
</code></pre>
<h5 id="heading-contingency-tables">Contingency Tables:</h5>
<p>This tool is your go-to for analyzing relationships between categorical variables (like gender and product preference). The table displays the frequency or proportion of observations for each combination of categories. </p>
<p>Contingency tables help you uncover associations between categories and identify potential dependencies.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd

<span class="hljs-comment"># Sample data (replace with your own categorical data)</span>
data = {<span class="hljs-string">'Gender'</span>: [<span class="hljs-string">'Male'</span>, <span class="hljs-string">'Female'</span>, <span class="hljs-string">'Male'</span>, <span class="hljs-string">'Female'</span>, <span class="hljs-string">'Male'</span>, <span class="hljs-string">'Female'</span>],
        <span class="hljs-string">'Product'</span>: [<span class="hljs-string">'A'</span>, <span class="hljs-string">'B'</span>, <span class="hljs-string">'C'</span>, <span class="hljs-string">'A'</span>, <span class="hljs-string">'B'</span>, <span class="hljs-string">'C'</span>]}
df = pd.DataFrame(data)

<span class="hljs-comment"># Create contingency table</span>
contingency_table = pd.crosstab(df[<span class="hljs-string">'Gender'</span>], df[<span class="hljs-string">'Product'</span>])
print(contingency_table)
</code></pre>
<h5 id="heading-grouped-summary-statistics">Grouped Summary Statistics:</h5>
<p>Imagine summarizing your data based on specific groups (like calculating average income by education level). </p>
<p>Grouped summary statistics provide descriptive measures (mean, median, etc.) for each group, allowing you to compare and contrast their characteristics. This can reveal how a categorical variable influences the distribution of a numerical variable, uncovering valuable insights.</p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np

<span class="hljs-comment"># Sample data (replace with your own dataset)</span>
data = {<span class="hljs-string">'Education'</span>: [<span class="hljs-string">'High School'</span>, <span class="hljs-string">'Bachelor'</span>, <span class="hljs-string">'Master'</span>, <span class="hljs-string">'High School'</span>, <span class="hljs-string">'Bachelor'</span>, <span class="hljs-string">'Master'</span>],
        <span class="hljs-string">'Income'</span>: [<span class="hljs-number">40000</span>, <span class="hljs-number">60000</span>, <span class="hljs-number">80000</span>, <span class="hljs-number">50000</span>, <span class="hljs-number">70000</span>, <span class="hljs-number">90000</span>]}
df = pd.DataFrame(data)

<span class="hljs-comment"># Calculate grouped summary statistics</span>
grouped_stats = df.groupby(<span class="hljs-string">'Education'</span>)[<span class="hljs-string">'Income'</span>].agg([<span class="hljs-string">'mean'</span>, <span class="hljs-string">'median'</span>, <span class="hljs-string">'std'</span>])
print(grouped_stats)
</code></pre>
<h4 id="heading-eda-in-action-real-world-applications-across-industries">EDA in Action: Real-World Applications Across Industries</h4>
<p>Exploratory Data Analysis (EDA) isn't confined to textbooks and research labs – it's a dynamic tool that's transforming industries and empowering professionals to make data-driven decisions that have real-world impact. </p>
<p>From retail giants to healthcare providers, from social scientists to environmental activists, EDA is the key to unlocking valuable insights and driving innovation.</p>
<h5 id="heading-business-data-driven-strategies-for-success">Business: Data-Driven Strategies for Success</h5>
<p>In the competitive business landscape, understanding your customers and market trends is paramount. EDA enables retailers to:</p>
<ul>
<li><strong>Uncover Hidden Customer Segments:</strong> Identify distinct groups of customers based on their preferences, demographics, and purchasing behavior. This knowledge allows for targeted marketing campaigns, personalized recommendations, and improved customer satisfaction.</li>
<li><strong>Optimize Pricing and Promotions:</strong> Analyze sales data to determine optimal pricing strategies, identify the most effective promotions, and maximize profitability.</li>
<li><strong>Enhance Supply Chain Management:</strong> Predict demand fluctuations, optimize inventory levels, and streamline logistics to reduce costs and improve efficiency.</li>
</ul>
<p>Meanwhile, financial institutions leverage EDA to:</p>
<ul>
<li><strong>Detect Fraudulent Activity:</strong> Identify unusual patterns in transaction data that might indicate fraudulent behavior, safeguarding customers and institutions alike.</li>
<li><strong>Manage Risk Effectively:</strong> Assess and mitigate risk by analyzing historical data, identifying potential vulnerabilities, and developing proactive risk management strategies.</li>
<li><strong>Optimize Investment Portfolios:</strong> Identify correlations between different asset classes, evaluate investment performance, and make informed decisions to maximize returns.</li>
</ul>
<h5 id="heading-healthcare-transforming-patient-care">Healthcare: Transforming Patient Care</h5>
<p>In the healthcare sector, EDA is instrumental in improving patient outcomes and transforming the delivery of care. Medical professionals utilize EDA to:</p>
<ul>
<li><strong>Identify Disease Patterns:</strong> Analyze patient data to identify patterns and risk factors associated with various diseases, leading to earlier diagnoses and more effective treatment plans.</li>
<li><strong>Personalize Treatment:</strong> Tailor treatment plans to individual patients based on their unique characteristics and medical history, leading to improved treatment outcomes and patient satisfaction.</li>
<li><strong>Optimize Resource Allocation:</strong> Analyze healthcare utilization patterns to identify areas where resources can be allocated more efficiently, improving access to care and reducing costs.</li>
</ul>
<h5 id="heading-social-sciences-understanding-society-through-data">Social Sciences: Understanding Society Through Data</h5>
<p>In the social sciences, EDA plays a crucial role in unraveling complex societal issues and informing policy decisions. Researchers utilize EDA to:</p>
<ul>
<li><strong>Explore Social Trends:</strong> Analyze demographic data, survey responses, and social media data to identify emerging trends, changing attitudes, and evolving social dynamics.</li>
<li><strong>Evaluate Policy Impact:</strong> Assess the effectiveness of social programs and policies by analyzing their impact on various outcome measures, such as poverty reduction, educational attainment, or crime rates.</li>
<li><strong>Inform Policy Decisions:</strong> Provide evidence-based insights to policymakers, helping them design and implement policies that address pressing social challenges and promote the well-being of communities.</li>
</ul>
<h5 id="heading-environmental-science-protecting-our-planet">Environmental Science: Protecting Our Planet</h5>
<p>In the face of environmental challenges, EDA is a valuable tool for understanding and mitigating the impact of human activities on our planet. Scientists utilize EDA to:</p>
<ul>
<li><strong>Analyze Climate Data:</strong> Identify long-term trends in temperature, precipitation, and other climate variables, helping to predict future climate scenarios and assess the potential impact of climate change.</li>
<li><strong>Monitor Environmental Health:</strong> Track changes in air and water quality, biodiversity, and other environmental indicators to assess the health of ecosystems and identify areas of concern.</li>
<li><strong>Inform Conservation Efforts:</strong> Use data-driven insights to guide conservation efforts, prioritize resource allocation, and develop sustainable solutions to environmental challenges.</li>
</ul>
<p>By harnessing the power of EDA, professionals across industries are empowered to make data-driven decisions that have a tangible impact on our world. Whether it's improving customer experiences, enhancing patient care, understanding societal trends, or protecting our planet, EDA is the key to unlocking the full potential of data and creating a brighter future.</p>
<h2 id="heading-5-applied-data-science-project">5. Applied Data Science Project</h2>
<p>If you're ready to launch a career in data analytics, data science, or software engineering, this project provides hands-on experience to accelerate your journey. </p>
<p>Leveraging the SuperStore dataset, we'll perform a comprehensive analysis that equips you with techniques applicable across diverse industries. This project emphasizes customer segmentation while building a robust data analysis skillset.</p>
<h3 id="heading-the-problem-untapped-data-potential">The Problem: Untapped Data Potential</h3>
<p>The sheer volume of data available to modern organizations is staggering, yet many lack the expertise to transform this data into actionable insights. This leads to missed opportunities for revenue growth, customer acquisition, and operational efficiency.</p>
<p>80% to 90% of the world's data is unstructured (<a target="_blank" href="https://www.deep-talk.ai/blog-posts/80-of-the-worlds-data-is-unstructured">Source</a>). Only 27% of executives can say they have a substantial amount of the data being generated from their customers (<a target="_blank" href="https://images.forbes.com/forbesinsights/StudyPDFs/SAS-DataElevatesTheConsumerExperience-REPORT.pdf">Source</a>). The value of the data economy in the EU is predicted to increase to over €550 billion by 2025 (<a target="_blank" href="https://www.consultancy.uk/news/32191/europes-data-economies-worth-550-billion-by-2025">Source</a>).</p>
<h3 id="heading-the-solution-strategic-data-analysis-with-the-superstore-dataset">The Solution: Strategic Data Analysis with the SuperStore Dataset</h3>
<p>In this project, we'll tackle this challenge head-on by conducting a comprehensive exploratory data analysis of the SuperStore dataset. Utilizing <strong>Python</strong> and <strong>Pandas</strong> within the <strong>Google Colab</strong> environment, we'll uncover hidden patterns, trends, and correlations that can inform strategic business decisions. Through this process, you'll learn to:</p>
<ul>
<li><strong>Segment Customers:</strong>  Delve into customer demographics, purchase behavior, and geographic location to identify distinct customer groups and tailor marketing strategies accordingly.</li>
<li><strong>Analyze Sales Trends:</strong> Uncover seasonal fluctuations, identify top-selling products, and pinpoint areas for potential growth.</li>
<li><strong>Unpack Geographic Insights:</strong> Examine sales and customer distribution across different regions, identifying potential opportunities for expansion or optimization.</li>
<li><strong>Assess Product Performance:</strong> Evaluate the success of individual products and product categories, guiding inventory management, marketing efforts, and product development decisions.</li>
</ul>
<h3 id="heading-beyond-analysis-effective-communication">Beyond Analysis: Effective Communication</h3>
<p>This project goes beyond analysis, teaching you to effectively communicate your findings to stakeholders. You'll learn to visualize data clearly, craft compelling narratives, and present actionable recommendations.</p>
<p>This project will serve as a guided exploration of the SuperStore dataset. By drawing on proven techniques, you'll gain the confidence to apply these skills to diverse data challenges.</p>
<p>We'll delve deeper than simple analysis, exploring customer segmentation's critical role within a broader data-driven strategy. You'll learn to communicate insights effectively for maximum impact.</p>
<p>This project will give you the hands-on experience and foundational tools you need to excel in data analyst, data scientist, and other data-driven roles. </p>
<p>You'll need a few things before you get started:</p>
<ul>
<li>The analysis utilizes the "Superstore Sales Dataset" <a target="_blank" href="https://www.kaggle.com/datasets/rohitsahoo/sales-forecasting/data">available on Kaggle here</a>.</li>
<li>For ease of use and to facilitate collaboration, a working copy of the analysis is <a target="_blank" href="https://colab.research.google.com/drive/1dOJO3X33GuDLvn_eb-oFEgbgAofTpwjA?usp=sharing">accessible via Google Colab here</a>.</li>
</ul>
<h3 id="heading-51-introduction-to-the-project">5.1 Introduction to the Project</h3>
<p>As a developer, you know the power of data. But have you ever harnessed that power to drive real-world business outcomes? The Superstore Analytics Project is your opportunity to do just that. This chapter will help you:</p>
<ul>
<li><strong>Become a Customer Insights Strategist:</strong> Uncover the hidden motivations behind customer behavior. Using Python libraries like Pandas and Scikit-learn, you'll segment customers into actionable groups and identify opportunities for personalized marketing that truly resonates.</li>
<li><strong>Pioneer New Markets and Optimize Supply Chains:</strong> Spatial analysis isn't just for maps – it's a powerful tool for identifying high-potential markets and streamlining logistics. Leverage libraries like Folium and NumPy to visualize data and guide strategic expansion decisions.</li>
<li><strong>Drive Revenue with High-Value Customer Retention:</strong> The Pareto principle applies to customers too: a small percentage drive a large portion of revenue. Identify these VIPs through data analysis, then develop tailored strategies to maximize their lifetime value.</li>
<li><strong>Master the Art of Product Profitability Analysis:</strong> Pandas and Matplotlib/Seaborn will be your allies as you dive into product sales data. Unearth top performers, uncover emerging trends, and make data-driven recommendations to optimize inventory and boost profitability.</li>
<li><strong>Elevate Store Performance through Location Intelligence:</strong> GeoPandas and Plotly are your tools for unlocking insights hidden in store location data. Identify underperforming stores, benchmark against high performers, and make targeted recommendations for improvement.</li>
<li><strong>Transform Operations through Data-Driven Optimization:</strong> Every step in the customer journey leaves a data trail. Analyze it to identify bottlenecks, streamline processes, and create a frictionless customer experience. Your mastery of Pandas, Seaborn, and network analysis will make you an invaluable asset.</li>
</ul>
<p>Now let's dive in.</p>
<h3 id="heading-the-superstore-sales-dataset-a-resource-for-retail-analysis-and-forecasting">The Superstore Sales Dataset: A Resource for Retail Analysis and Forecasting</h3>
<p>This comprehensive dataset offers four years of detailed sales records from a global superstore. It provides a valuable foundation for us to understand customer behavior, optimize operations, and accurately predict future trends.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/Screenshot-2024-05-09-at-11.11.02.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshot from the Superstore dataset</em></p>
<p><strong>Dataset Contents:</strong></p>
<ul>
<li><strong>Granular Sales Data:</strong> Includes order dates, product categories, shipping methods, customer demographics, and sales figures.</li>
<li><strong>Time Series Analysis:</strong> Daily data enables the examination of short and long-term sales patterns, along with the influence of seasons, promotions, and other relevant events.</li>
<li><strong>User-Friendly Format:</strong> The dataset's structure is clear and well-organized, facilitating analysis for data professionals at various experience levels.</li>
</ul>
<p><strong>Potential Applications:</strong></p>
<ul>
<li><strong>Exploratory Data Analysis (EDA):</strong> Discover patterns within the data, revealing high-demand periods, top products, and customer preferences.</li>
<li><strong>Predictive Modeling:</strong> Develop time series forecasting models to anticipate sales with increased precision. This informs decision-making around inventory, resource allocation, and marketing campaigns.</li>
<li><strong>Strategic Optimization:</strong> Translate data-driven insights into actions that improve operational efficiency, promotional effectiveness, and overall profitability.</li>
</ul>
<p><strong>Dataset Advantages:</strong></p>
<ul>
<li><strong>Real-World Complexity:</strong> Data mirrors the multifaceted nature of a global retail operation, offering greater realism than simulated datasets.</li>
<li><strong>Adaptive to Your Needs:</strong> Supports a range of analytical techniques, from basic trend identification to sophisticated forecasting methodologies.</li>
</ul>
<p>This dataset can help you learn how to unlock valuable insights from real-world retail data – that's why we're using it here.</p>
<h3 id="heading-code-walkthrough">Code Walkthrough:</h3>
<p>Now we'll go through the Python code piece by piece so you can put this project together yourself. I'll explain each section and its outcome within the context of retail sales analysis.</p>
<h4 id="heading-import-libraries">Import Libraries:</h4>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns
<span class="hljs-keyword">from</span> google.colab <span class="hljs-keyword">import</span> drive
</code></pre>
<ul>
<li><strong><code>pandas</code>:</strong>  The cornerstone for data manipulation and analysis. Used for working with DataFrames (like spreadsheet structures).</li>
<li><strong><code>numpy</code>:</strong> Provides tools for numerical computations, arrays, and mathematical functions.</li>
<li><strong><code>matplotlib.pyplot</code>:</strong>  The core plotting library in Python, enabling creation of charts and graphs.</li>
<li><strong><code>seaborn</code>:</strong> Builds on Matplotlib, offering a higher-level interface for attractive statistical visualizations.</li>
<li><strong><code>google.colab import drive</code>:</strong> For working with Google Drive in a Colab environment, allowing file access.</li>
</ul>
<h4 id="heading-data-loading-and-preparation">Data Loading and Preparation:</h4>
<pre><code class="lang-python">drive.mount(<span class="hljs-string">'/content/drive'</span>)
df = pd.read_csv(<span class="hljs-string">r"/content/sample_data/train.csv"</span>)
df.head()
df.info()
</code></pre>
<ul>
<li><strong><code>drive.mount('/content/drive')</code>:</strong> Mounts your Google Drive, enabling access to files within your Colab notebook.</li>
<li><strong><code>df = pd.read_csv(...)</code>:</strong> Reads the CSV data file into a pandas DataFrame named 'df'.</li>
<li><strong><code>df.head()</code>:</strong> Displays the first few rows of the DataFrame, giving a quick preview of the data.</li>
<li><strong><code>df.info()</code>:</strong> Summarizes the DataFrame, showing column names, data types, and non-null counts.</li>
</ul>
<h4 id="heading-handling-missing-data">Handling Missing Data:</h4>
<pre><code class="lang-python">null_count = df[<span class="hljs-string">'Postal Code'</span>].isnull().sum()
print(null_count)
df[<span class="hljs-string">"Postal Code"</span>].fillna(<span class="hljs-number">0</span>, inplace = <span class="hljs-literal">True</span>)
df[<span class="hljs-string">'Postal Code'</span>] = df[<span class="hljs-string">'Postal Code'</span>].astype(int)
df.info()
</code></pre>
<ul>
<li><strong><code>null_count = ...</code>:</strong> Counts the number of missing values (<code>NaN</code>) in the 'Postal Code' column.</li>
<li><strong><code>df["Postal Code"].fillna(0, inplace = True)</code>:</strong>  Replaces missing 'Postal Code' values with 0 directly in the DataFrame.</li>
<li><strong><code>df['Postal Code'] = ...astype(int)</code>:</strong>  Converts the 'Postal Code' column to an integer data type.</li>
<li><strong><code>df.info()</code>:</strong> Checks the DataFrame again to ensure data types and null values are handled correctly.</li>
</ul>
<h4 id="heading-checking-for-duplicates">Checking for Duplicates:</h4>
<pre><code class="lang-python"><span class="hljs-keyword">if</span> df.duplicated().sum() &gt; <span class="hljs-number">0</span>: 
  print(<span class="hljs-string">"Duplicates exist in the DataFrame."</span>)
<span class="hljs-keyword">else</span>:
  print(<span class="hljs-string">"No duplicates found in the DataFrame."</span>)
</code></pre>
<ul>
<li><strong><code>df.duplicated().sum() &gt; 0:</code></strong> This condition checks if there are any duplicated rows in the DataFrame.</li>
<li><strong><code>if...else</code>:</strong> Prints an appropriate message indicating whether duplicates were found.</li>
</ul>
<h4 id="heading-exploratory-data-analysis-eda">Exploratory Data Analysis (EDA)</h4>
<h5 id="heading-customer-segmentation">Customer Segmentation</h5>
<p>Our first step in understanding our customer base is to identify the different segments that exist within it. Let's see how the code helps us do this:</p>
<pre><code class="lang-python">types_of_customers = df[<span class="hljs-string">'Segment'</span>].unique()
print(types_of_customers)
</code></pre>
<p>This line of code takes a peek at your dataset's 'Segment' column and extracts all the unique values found within. It's likely that each of these values represents a distinct group of customers who share certain characteristics or behaviors.</p>
<p>Next, we want to know how big each of these segments is:</p>
<pre><code class="lang-python">number_of_customers = df[<span class="hljs-string">'Segment'</span>].value_counts().reset_index()
number_of_customers = number_of_customers.rename(columns={<span class="hljs-string">'Segment'</span>: <span class="hljs-string">'Total Customers'</span>})
print(number_of_customers.head())
</code></pre>
<p>This code snippet counts how many customers fall into each segment. To make the results easier to understand, we rename a column for clarity.</p>
<ol>
<li><strong>Visualizing the Distribution</strong></li>
</ol>
<p>Now, let's create a pie chart to visualize the breakdown of our customer base:</p>
<pre><code class="lang-python">plt.pie(number_of_customers[<span class="hljs-string">'count'</span>], labels=number_of_customers[<span class="hljs-string">'Total Customers'</span>], autopct=<span class="hljs-string">'%1.1f%%'</span>) 
plt.title(<span class="hljs-string">'Distribution of Clients'</span>)
plt.show()
</code></pre>
<p>This pie chart gives us a quick visual understanding of the relative sizes of our customer segments.</p>
<ol start="2">
<li><strong>Analyzing Sales Across Segments</strong></li>
</ol>
<p>Knowing which segments are the most numerous is helpful, but which ones drive the most sales? Let's find out:</p>
<pre><code class="lang-python">sales_per_segment = df.groupby(<span class="hljs-string">'Segment'</span>)[<span class="hljs-string">'Sales'</span>].sum().reset_index()
sales_per_segment = sales_per_segment.rename(columns={<span class="hljs-string">'Segment'</span>: <span class="hljs-string">'Customer Type'</span>, <span class="hljs-string">'Sales'</span>: <span class="hljs-string">'Total Sales'</span>})
print(sales_per_segment) 

<span class="hljs-comment"># Bar Chart:</span>
plt.bar(sales_per_segment[<span class="hljs-string">'Customer Type'</span>], sales_per_segment[<span class="hljs-string">'Total Sales'</span>])

<span class="hljs-comment"># Labels and Title</span>
plt.title(<span class="hljs-string">'Sales per Customer Category'</span>)
plt.xlabel(<span class="hljs-string">'Customer Type'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.show()

<span class="hljs-comment"># Pie Chart:</span>
plt.pie(sales_per_segment[<span class="hljs-string">'Total Sales'</span>], labels=sales_per_segment[<span class="hljs-string">'Customer Type'</span>], autopct=<span class="hljs-string">'%1.1f%%'</span>)

<span class="hljs-comment"># Title</span>
plt.title(<span class="hljs-string">'Sales per Customer Category'</span>)
plt.show()
</code></pre>
<p>This code calculates the total sales generated by each customer segment. We then create bar and pie charts to visualize this sales performance, helping us identify the most valuable segments to the business.</p>
<ol start="3">
<li><strong>The Power of Segmentation</strong></li>
</ol>
<p>By understanding the composition of your customer base, their sizes, and how they contribute to sales, you gain valuable insights to guide your business strategy. This knowledge empowers you to  make informed decisions about marketing campaigns, resource allocation, and even product development to better serve your customers.</p>
<h5 id="heading-customer-loyalty">Customer Loyalty</h5>
<pre><code class="lang-python">customer_order_frequency = df.groupby([<span class="hljs-string">'Customer ID'</span>, <span class="hljs-string">'Customer Name'</span>, <span class="hljs-string">'Segment'</span>])[<span class="hljs-string">'Order ID'</span>].count().reset_index()
customer_order_frequency.rename(columns={<span class="hljs-string">'Order ID'</span>: <span class="hljs-string">'Total Orders'</span>}, inplace=<span class="hljs-literal">True</span>)

repeat_customers = customer_order_frequency[customer_order_frequency[<span class="hljs-string">'Total Orders'</span>] &gt;= <span class="hljs-number">1</span>]
repeat_customers_sorted = repeat_customers.sort_values(by=<span class="hljs-string">'Total Orders'</span>, ascending=<span class="hljs-literal">False</span>)
print(repeat_customers_sorted.head(<span class="hljs-number">12</span>).reset_index(drop=<span class="hljs-literal">True</span>))
</code></pre>
<ul>
<li><strong><code>customer_order_frequency = ...</code></strong>: Calculates order frequency (count) for each unique customer.</li>
<li><strong><code>repeat_customers = ...</code></strong>: Isolates customers who have placed more than one order.</li>
<li><strong><code>repeat_customers_sorted = ...</code></strong>: Sorts repeat customers by their order frequency.</li>
<li><strong><code>print(...)</code>:</strong> Displays top repeat customers.</li>
</ul>
<p><strong>Finding Your Top-Spending Customers</strong></p>
<p>Identifying who spends the most at your store is valuable. This lets you focus your marketing efforts and create special programs for your most loyal, high-value customers. Let's break down how to do this with a bit of Python and pandas.</p>
<p><strong>Prerequisites:</strong></p>
<ul>
<li>You have a dataset (usually a CSV file) loaded into a pandas DataFrame named <code>df</code>.</li>
<li>Your DataFrame includes columns like "Customer ID", "Customer Name", "Segment", and "Sales".</li>
</ul>
<p><strong>Step 1: Group and Sum</strong></p>
<pre><code class="lang-python">customer_sales = df.groupby([<span class="hljs-string">'Customer ID'</span>, <span class="hljs-string">'Customer Name'</span>, <span class="hljs-string">'Segment'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We use <code>groupby</code> to bundle together all the purchases made by each unique customer (based on their ID and other details).</li>
<li>We focus on the 'Sales' column and calculate the <code>sum</code> to get their total spending.</li>
<li><code>reset_index()</code> tidies up the output so it looks like a normal table again.</li>
</ul>
<p><strong>Step 2: Sorting for the Top</strong></p>
<pre><code class="lang-python">top_spenders = customer_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We take our <code>customer_sales</code> table and <code>sort_values</code> based on the 'Sales' column.</li>
<li><code>ascending=False</code> puts the customers with the highest spending at the top of our list.</li>
</ul>
<p><strong>Step 3: Print the Results</strong></p>
<pre><code class="lang-python">print(top_spenders.head(<span class="hljs-number">10</span>).reset_index(drop=<span class="hljs-literal">True</span>))
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>.head(10)</code> grabs the first 10 rows, showing our top 10 spenders.</li>
<li><code>.reset_index(drop=True)</code> gives our results a clean index from 0 to 9, making it easier to read.</li>
</ul>
<p><strong>The Output:</strong></p>
<p>You'll get a nice table showing your top customers, their details, and their total spending.</p>
<p>Now that you know who your top spenders are, you can:</p>
<ul>
<li><strong>Target promotions directly to them:</strong> They're likely to be receptive to offers and new products.</li>
<li><strong>Build loyalty programs:</strong> Reward their spending with exclusive benefits.</li>
<li><strong>Personalize their experience:</strong> Use their purchase history to recommend other things they might like.</li>
</ul>
<h5 id="heading-understanding-your-shipping-methods">Understanding Your Shipping Methods</h5>
<p>Let's figure out which shipping options your customers use most often. This helps you make sure you're offering the right choices and can spot any potential areas for improvement.</p>
<p><strong>Prerequisites</strong></p>
<ul>
<li>You have your sales data loaded as a pandas DataFrame named <code>df</code>.</li>
<li>This DataFrame has a column named 'Ship Mode' that indicates the shipping method used for each order.</li>
</ul>
<p><strong>Step 1:  What Shipping Methods Do You Offer?</strong></p>
<pre><code class="lang-python">types_of_customers = df[<span class="hljs-string">'Ship Mode'</span>].unique()
print(types_of_customers)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We grab the 'Ship Mode' column and find all the <code>unique</code> shipping options within it.</li>
<li>This line neatly prints a list of the different shipping methods you use.</li>
</ul>
<p><strong>Step 2: How Popular is Each Method?</strong></p>
<pre><code class="lang-python">shipping_model = df[<span class="hljs-string">'Ship Mode'</span>].value_counts().reset_index()
shipping_model = shipping_model.rename(columns={<span class="hljs-string">'index'</span>:<span class="hljs-string">'Use Frequency'</span>, <span class="hljs-string">'Ship Mode'</span>: <span class="hljs-string">'Mode of Shipment'</span>, <span class="hljs-string">'count'</span> : <span class="hljs-string">'Use Frequency'</span>})
print(shipping_model)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>value_counts()</code> counts how many times each shipping method appears in your data.</li>
<li>We do some tidying up with <code>reset_index()</code> and <code>rename()</code> to make the output look like a clear table.</li>
<li>You now have a table showing each 'Mode of Shipment' and its 'Use Frequency'!</li>
</ul>
<p><strong>Step 3: Visualizing the Results</strong></p>
<pre><code class="lang-python">plt.pie(shipping_model[<span class="hljs-string">'Use Frequency'</span>], labels=shipping_model[<span class="hljs-string">'Mode of Shipment'</span>], autopct=<span class="hljs-string">'%1.1f%%'</span>) 
plt.title(<span class="hljs-string">'Popular Mode Of Shipment'</span>)
plt.show()
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We create a pie chart to visualize how much each shipping method is used. Each slice represents a method, and its size shows its popularity.</li>
<li><code>autopct='%1.1f%%'</code> adds percentages to the pie chart for clarity.</li>
</ul>
<p><strong>What This Tells You</strong>:</p>
<ul>
<li><strong>Customer Preferences:</strong> See which shipping methods are most popular. Do customers lean towards speed or affordability?</li>
<li><strong>Potential for Improvement:</strong> Are any important shipping methods rarely used? Maybe they're too expensive, or customers aren't aware of them.</li>
<li><strong>Data for Decisions:</strong> Use this info to negotiate better rates with carriers, offer shipping options your customers want, and streamline your operations.</li>
</ul>
<h5 id="heading-exploring-sales-across-locations">Exploring Sales Across Locations</h5>
<p>Knowing where your customers are coming from and where the most sales happen is valuable for targeting your efforts. Let's dive into the code.</p>
<p><strong>Prerequisites</strong></p>
<ul>
<li>You have a pandas DataFrame named <code>df</code>.</li>
<li>It contains columns named 'State' and 'City' (representing customer locations) and 'Sales'.</li>
</ul>
<p><strong>Step 1: Customers by State</strong></p>
<pre><code class="lang-python">state = df[<span class="hljs-string">'State'</span>].value_counts().reset_index()
state = state.rename(columns={<span class="hljs-string">'index'</span>:<span class="hljs-string">'State'</span>, <span class="hljs-string">'State'</span>:<span class="hljs-string">'Number_of_customers'</span>})
print(state.head(<span class="hljs-number">20</span>))
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We count how many customers are in each state using <code>value_counts()</code>.</li>
<li>We tidy up the output and rename columns for clarity.</li>
<li>This shows a table of states with the 'Number_of_customers' in each.</li>
</ul>
<p><strong>Step 2: Customers by City</strong></p>
<pre><code class="lang-python">city = df[<span class="hljs-string">'City'</span>].value_counts().reset_index()
city= city.rename(columns={<span class="hljs-string">'index'</span>:<span class="hljs-string">'City'</span>, <span class="hljs-string">'City'</span>:<span class="hljs-string">'Number_of_customers'</span>})
print(city.head(<span class="hljs-number">15</span>))
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>Very similar to the above, but we focus on 'City' to see customer concentration within states.</li>
<li>This gives you a table of your top cities based on customer count.</li>
</ul>
<p><strong>Step 3: Sales by State</strong></p>
<pre><code class="lang-python">state_sales = df.groupby([<span class="hljs-string">'State'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()
top_sales = state_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)
print(top_sales.head(<span class="hljs-number">20</span>).reset_index(drop=<span class="hljs-literal">True</span>))
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We group by 'State' and sum the 'Sales' to see total spending per state.</li>
<li>Sorting shows your top-earning states.</li>
</ul>
<p><strong>Step 4: Sales by City</strong></p>
<pre><code class="lang-python">city_sales = df.groupby([<span class="hljs-string">'City'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()
top_city_sales = city_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)
print(top_city_sales.head(<span class="hljs-number">20</span>).reset_index(drop=<span class="hljs-literal">True</span>))
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>Again, we group, but now by 'City' to find total sales per city.</li>
<li>Sorting reveals your highest-earning cities overall.</li>
</ul>
<p><strong>Step 5: Sales by State and City (Optional)</strong></p>
<pre><code class="lang-python">state_city_sales = df.groupby([<span class="hljs-string">'State'</span>,<span class="hljs-string">'City'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()
print(state_city_sales.head(<span class="hljs-number">20</span>))
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>Combines 'State' and 'City' for maximum detail about where your sales are concentrated.</li>
</ul>
<p><strong>Insights You Gain</strong>:</p>
<ul>
<li><strong>Target Marketing:</strong> Focus on high-performing states/cities where your customer base is large.</li>
<li><strong>Expansion Planning:</strong> Spot states with lots of customers but low sales – maybe there's room to grow.</li>
<li><strong>Localize Offers:</strong> Tailor promotions to specific locations based on their spending habits.</li>
</ul>
<h5 id="heading-exploring-your-product-mix">Exploring Your Product Mix</h5>
<p>Understanding what products drive your sales is crucial. Let's break down how your code helps you analyze this.</p>
<p><strong>Prerequisites</strong></p>
<ul>
<li>You have a pandas DataFrame named <code>df</code>.</li>
<li>It contains columns named 'Category' (broad product type), 'Sub-Category' (more specific product type), and 'Sales'.</li>
</ul>
<p><strong>Step 1: What Products Do You Carry?</strong></p>
<pre><code class="lang-python">products = df[<span class="hljs-string">'Category'</span>].unique()
print(products)

product_subcategory = df[<span class="hljs-string">'Sub-Category'</span>].unique()
print(product_subcategory)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We use <code>.unique()</code> to find all the different categories and sub-categories in your inventory.</li>
<li>This provides a snapshot of your product offerings.</li>
</ul>
<p><strong>Step 2: How Many Sub-Categories?</strong></p>
<pre><code class="lang-python">product_subcategory = df[<span class="hljs-string">'Sub-Category'</span>].nunique()
print(product_subcategory)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>.nunique()</code> counts the number of unique sub-categories, showing the breadth of your product selections within broader categories.</li>
</ul>
<p><strong>Step 3: Category and Sub-Category Breakdown</strong></p>
<pre><code class="lang-python">subcategory_count = df.groupby(<span class="hljs-string">'Category'</span>)[<span class="hljs-string">'Sub-Category'</span>].nunique().reset_index()
subcategory_count = subcategory_count.sort_values(by=<span class="hljs-string">'Sub-Category'</span>, ascending=<span class="hljs-literal">False</span>)
print(subcategory_count)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We group by 'Category' and count the unique sub-categories within each.</li>
<li>Sorting reveals which categories offer the greatest product variety.</li>
</ul>
<p><strong>Step 4: Sales by Category and Sub-Category</strong></p>
<pre><code class="lang-python">subcategory_count_sales = df.groupby([<span class="hljs-string">'Category'</span>,<span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()
print(subcategory_count_sales)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We get granular, grouping by both 'Category' and 'Sub-Category' to calculate total sales for each combination.</li>
<li>This helps spot your best-selling individual products as well as strong categories.</li>
</ul>
<p><strong>Step 5: Top Categories by Sales</strong></p>
<pre><code class="lang-python">product_category = df.groupby([<span class="hljs-string">'Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()
top_product_category = product_category.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)
print(top_product_category.reset_index(drop=<span class="hljs-literal">True</span>))

<span class="hljs-comment"># Plotting a pie chart</span>
plt.pie(...) <span class="hljs-comment"># Your pie chart code</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We group by 'Category' and sum 'Sales' to get total revenue per category.</li>
<li>Sorting shows your top earners.</li>
<li>The pie chart visualizes the contribution of each category to overall sales</li>
</ul>
<p><strong>Step 6: Top Sub-Categories by Sales</strong></p>
<pre><code class="lang-python">product_subcategory = df.groupby([<span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()
top_product_subcategory = product_subcategory.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)
print(top_product_subcategory.reset_index(drop=<span class="hljs-literal">True</span>))

<span class="hljs-comment"># Bar Chart</span>
top_product_subcategory = ... <span class="hljs-comment"># Your bar chart code</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We focus on 'Sub-Category' to reveal your best-selling individual product types.</li>
<li>The bar chart ranks sub-categories by their sales contribution.</li>
</ul>
<p><strong>Insights You Gain</strong>:</p>
<ul>
<li><strong>Inventory Decisions:</strong> Stock up on items in high-performing categories and sub-categories. Consider phasing out those that sell poorly.</li>
<li><strong>Spot Niche Success:</strong> Uncover less-obvious sub-categories with surprising sales potential, suggesting areas to expand.</li>
<li><strong>Targeted Promotions:</strong> Design promotions around your top-performing categories or individual products.</li>
</ul>
<h5 id="heading-product-analysis">Product Analysis</h5>
<p>Let's do a walkthrough of the sales analysis code, ensuring we cover each section and its role in understanding trends over time.</p>
<p><strong>Prerequisites</strong></p>
<ul>
<li>You have a pandas DataFrame named <code>df</code>.</li>
<li>It contains columns named 'Order Date' (representing when orders were placed) and 'Sales'.</li>
</ul>
<p><strong>Step 1:  Preparing Your Date Data</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Convert the "Order Date" column to datetime format</span>
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>], dayfirst=<span class="hljs-literal">True</span>)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We use <code>pd.to_datetime()</code> to transform 'Order Date' into a format pandas can work with for time-based analysis.</li>
<li><code>dayfirst=True</code> might be needed if your dates are in a format like "Day/Month/Year."</li>
</ul>
<p><strong>Step 2: Yearly Sales Analysis</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Group by year and calculate total sales</span>
yearly_sales = df.groupby(df[<span class="hljs-string">'Order Date'</span>].dt.year)[<span class="hljs-string">'Sales'</span>].sum().reset_index()
yearly_sales = yearly_sales.rename(columns={<span class="hljs-string">'Order Date'</span>: <span class="hljs-string">'Year'</span>, <span class="hljs-string">'Sales'</span>:<span class="hljs-string">'Total Sales'</span>})
print(yearly_sales)

<span class="hljs-comment"># Bar Graph</span>
plt.bar(yearly_sales[<span class="hljs-string">'Year'</span>], yearly_sales[<span class="hljs-string">'Total Sales'</span>]) 
<span class="hljs-comment"># ... (labels and plotting code) </span>

<span class="hljs-comment"># Line Graph</span>
plt.plot(yearly_sales[<span class="hljs-string">'Year'</span>], yearly_sales[<span class="hljs-string">'Total Sales'</span>], marker=<span class="hljs-string">'o'</span>, linestyle=<span class="hljs-string">'-'</span>)
<span class="hljs-comment"># ... (labels and plotting code)</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We group by the year portion of 'Order Date' and sum the 'Sales' for each year.</li>
<li>This table shows your annual sales figures.</li>
<li>The bar graph visualizes annual sales with each bar representing a year.</li>
<li>The line graph connects your yearly sales data points, highlighting trends across time.</li>
</ul>
<p><strong>Step 3: Quarterly Sales (2018 Example)</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Filter data for 2018 </span>
year_sales = df[df[<span class="hljs-string">'Order Date'</span>].dt.year == <span class="hljs-number">2018</span>]

<span class="hljs-comment"># Quarterly sales for 2018</span>
quarterly_sales = year_sales.resample(<span class="hljs-string">'Q'</span>, on=<span class="hljs-string">'Order Date'</span>)[<span class="hljs-string">'Sales'</span>].sum().reset_index()
quarterly_sales = quarterly_sales.rename(columns={<span class="hljs-string">'Order Date'</span>: <span class="hljs-string">'Quarter'</span>, <span class="hljs-string">'Sales'</span>:<span class="hljs-string">'Total Sales'</span>})
print(quarterly_sales)

<span class="hljs-comment"># Line graph for 2018 quarterly sales</span>
plt.plot(quarterly_sales[<span class="hljs-string">'Quarter'</span>], quarterly_sales[<span class="hljs-string">'Total Sales'</span>], marker=<span class="hljs-string">'o'</span>, linestyle=<span class="hljs-string">'--'</span>)
<span class="hljs-comment"># ... (labels and plotting code)</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We isolate the data for 2018.</li>
<li><code>.resample('Q')</code> groups by quarter, summing 'Sales'.</li>
<li>The table shows your quarterly sales for 2018.</li>
<li>The line graph plots quarterly sales, potentially revealing seasonal patterns within the year.</li>
</ul>
<p><strong>Step 4: Monthly Sales (2018 Example)</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Monthly sales for 2018</span>
monthly_sales = year_sales.resample(<span class="hljs-string">'M'</span>, on=<span class="hljs-string">'Order Date'</span>)[<span class="hljs-string">'Sales'</span>].sum().reset_index()
monthly_sales = monthly_sales.rename(columns={<span class="hljs-string">'Order Date'</span>:<span class="hljs-string">'Month'</span>, <span class="hljs-string">'Sales'</span>:<span class="hljs-string">'Total Montly Sales'</span>})
print(monthly_sales)  

<span class="hljs-comment"># Line graph for 2018 monthly sales</span>
plt.plot(monthly_sales[<span class="hljs-string">'Month'</span>], monthly_sales[<span class="hljs-string">'Total Montly Sales'</span>], marker=<span class="hljs-string">'o'</span>, linestyle=<span class="hljs-string">'--'</span>)
<span class="hljs-comment"># ... (labels and plotting code)</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>Very similar to quarterly, but  <code>.resample('M')</code> groups by month for more fine-grained insights.</li>
<li>The table shows your monthly sales for 2018.</li>
<li>The line graph can uncover even shorter-term trends or month-specific spikes.</li>
</ul>
<p><strong>Insights You Gain</strong>:</p>
<ul>
<li><strong>Overall Growth:</strong> Do sales increase year-over-year?</li>
<li><strong>Seasonality:</strong> Are there busy and slow periods during the year?</li>
<li><strong>Short-Term Fluctuations:</strong> Spot months with unusual sales patterns needing further investigation.</li>
</ul>
<h5 id="heading-sales-trends">Sales Trends</h5>
<p>Are your sales peaking at the right times? Do you spot the early signs of upcoming slowdowns? Let's decipher the code to find the answers.</p>
<p><strong>Prerequisites:</strong></p>
<ul>
<li>You have a pandas DataFrame named <code>df</code>.</li>
<li>It contains columns named 'Order Date' and 'Sales'.</li>
</ul>
<p><strong>Step 1: Prepare Your Data</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Convert the "Order Date" column to datetime format</span>
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>], dayfirst=<span class="hljs-literal">True</span>)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>pd.to_datetime()</code> transforms the 'Order Date' column into a format suitable for time-based analysis.</li>
<li><code>dayfirst=True</code> might be needed if your dates are in a format like "Day/Month/Year."</li>
</ul>
<p><strong>Step 2: Monthly Sales Trends</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Group by months and calculate total sales</span>
monthly_sales = df.groupby(df[<span class="hljs-string">'Order Date'</span>].dt.to_period(<span class="hljs-string">'M'</span>))[<span class="hljs-string">'Sales'</span>].sum() 

<span class="hljs-comment"># Plot monthly sales trends</span>
plt.figure(figsize=(<span class="hljs-number">12</span>, <span class="hljs-number">26</span>))  
plt.subplot(<span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>) 
monthly_sales.plot(kind=<span class="hljs-string">'line'</span>, marker=<span class="hljs-string">'o'</span>) 
<span class="hljs-comment"># ... (labels and plotting code)</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>.dt.to_period('M')</code> groups dates by month.</li>
<li><code>['Sales'].sum()</code> calculates total sales per month.</li>
<li><code>kind='line'</code>, <code>marker='o'</code> create a line plot with markers for visual clarity.</li>
</ul>
<p><strong>Step 3: Quarterly and Yearly Trends</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Code for quarterly sales (very similar to monthly)</span>
quarterly_sales = df.groupby(df[<span class="hljs-string">'Order Date'</span>].dt.to_period(<span class="hljs-string">'Q'</span>))[<span class="hljs-string">'Sales'</span>].sum() 
<span class="hljs-comment"># ... (plotting code)</span>

<span class="hljs-comment"># Code for yearly sales </span>
yearly_sales = df.groupby(df[<span class="hljs-string">'Order Date'</span>].dt.to_period(<span class="hljs-string">'Y'</span>))[<span class="hljs-string">'Sales'</span>].sum() 
<span class="hljs-comment"># ... (plotting code)</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>The structure mirrors the monthly sales analysis. We change <code>to_period()</code> to 'Q' for quarters and 'Y' for years.</li>
</ul>
<p><strong>Step 4: Daily Sales Over Time</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Group by "Order Date" and calculate the sum of sales</span>
df_summary = df.groupby(<span class="hljs-string">'Order Date'</span>)[<span class="hljs-string">'Sales'</span>].sum().reset_index()

<span class="hljs-comment"># Create a line plot</span>
plt.figure(figsize=(<span class="hljs-number">30</span>, <span class="hljs-number">8</span>))
plt.plot(df_summary[<span class="hljs-string">'Order Date'</span>], df_summary[<span class="hljs-string">'Sales'</span>], marker=<span class="hljs-string">'o'</span>, linestyle=<span class="hljs-string">'-'</span>)
<span class="hljs-comment"># ... (labels and plotting code)</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We group directly by 'Order Date' without any date conversion for a day-by-day sales view.</li>
<li>This line plot can reveal very short-term fluctuations or spikes in sales.</li>
</ul>
<p><strong>What You Gain From These Visualizations</strong>:</p>
<ul>
<li><strong>Monthly Trends:</strong> Identify seasonal sales patterns across the year.</li>
<li><strong>Quarterly Trends:</strong> Spot broader trends, perhaps tied to business cycles or marketing efforts.</li>
<li><strong>Yearly Trends:</strong> Observe long-term growth, decline, or stagnation in your sales.</li>
<li><strong>Daily Fluctuation</strong>s: Pinpoint specific days with unusually high or low sales, potentially needing more investigation.</li>
</ul>
<h5 id="heading-geographical-mapping-analysis">Geographical Mapping Analysis</h5>
<p>Ready to target your marketing dollars? Let's visualize your sales by state to pinpoint areas with the most potential.</p>
<p><strong>Prerequisites:</strong></p>
<ul>
<li>You have a pandas DataFrame named <code>df</code>.</li>
<li>It contains columns named 'State' (full state names) and 'Sales'.</li>
</ul>
<p><strong>Step 1: Import Libraries</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> plotly.graph_objects <span class="hljs-keyword">as</span> go 
<span class="hljs-keyword">from</span> plotly.subplots <span class="hljs-keyword">import</span> make_subplots 
<span class="hljs-keyword">import</span> plotly.io <span class="hljs-keyword">as</span> pio
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>plotly.graph_objects</code> provides tools for creating interactive Plotly graphs, including choropleth maps.</li>
<li><code>plotly.subplots</code> is for complex layouts with multiple plots (not used in this specific code).</li>
<li><code>plotly.io</code> prepares Plotly for use in a Jupyter Notebook environment.</li>
</ul>
<p><strong>Step 2: State Mapping</strong></p>
<pre><code class="lang-python">all_state_mapping = { ... } <span class="hljs-comment"># Your dictionary mapping state names to abbreviations</span>
</code></pre>
<p><strong>Explanation:</strong> </p>
<ul>
<li>Creates a dictionary for converting full state names to their standard 2-letter abbreviations, which are used by Plotly for map labels.</li>
</ul>
<p><strong>Step 3: Prepare Data</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Add Abbreviation</span>
df[<span class="hljs-string">'Abbreviation'</span>] = df[<span class="hljs-string">'State'</span>].map(all_state_mapping)

<span class="hljs-comment"># Calculate Sales per State</span>
sum_of_sales = df.groupby(<span class="hljs-string">'State'</span>)[<span class="hljs-string">'Sales'</span>].sum().reset_index()

<span class="hljs-comment"># Add Abbreviation to sum_of_sales (for joining later in Plotly)</span>
sum_of_sales[<span class="hljs-string">'Abbreviation'</span>] = sum_of_sales[<span class="hljs-string">'State'</span>].map(all_state_mapping)
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We add a new 'Abbreviation' column to the main DataFrame.</li>
<li>We group by 'State' and calculate total 'Sales' for each state.</li>
<li>We add the 'Abbreviation' column to the sales summary, too, to connect it with the map data.</li>
</ul>
<p><strong>Step 4: Create Choropleth Map (Plotly)</strong></p>
<pre><code class="lang-python">fig = go.Figure(data=go.Choropleth(
    locations=sum_of_sales[<span class="hljs-string">'Abbreviation'</span>], <span class="hljs-comment"># State abbreviations</span>
    locationmode=<span class="hljs-string">'USA-states'</span>, 
    z=sum_of_sales[<span class="hljs-string">'Sales'</span>], <span class="hljs-comment"># Sales values determine color intensity</span>
    hoverinfo=<span class="hljs-string">'location+z'</span>, <span class="hljs-comment"># Hover shows state + sales value</span>
    showscale=<span class="hljs-literal">True</span> <span class="hljs-comment"># Add a color scale for interpreting values visually</span>
))

fig.update_geos(projection_type=<span class="hljs-string">"albers usa"</span>) 
fig.update_layout(
    geo_scope=<span class="hljs-string">'usa'</span>,
    title=<span class="hljs-string">'Total Sales by U.S. State'</span>
)

fig.show()
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>go.Choropleth</code> creates a US map where state colors represent sales figures.</li>
<li><code>update_geos</code> and <code>geo_scope</code> are for proper map display.</li>
</ul>
<p><strong>Step 5: Horizontal Bar Graph (Seaborn)</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Calculate sales per state (repeated - you already have this)</span>
sum_of_sales = ... 

<span class="hljs-comment"># Sort by sales in descending order</span>
sum_of_sales = sum_of_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Create bar graph</span>
plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">13</span>))
ax = sns.barplot(x=<span class="hljs-string">'Sales'</span>, y=<span class="hljs-string">'State'</span>, data=sum_of_sales, errorbar=<span class="hljs-literal">None</span>)
<span class="hljs-comment"># ... (labels and plotting code)</span>
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We re-calculate our sales summary (this was already done earlier).</li>
<li>Sorting positions states with the highest sales at the top.</li>
<li>Seaborn's <code>barplot</code> creates a horizontal bar chart for easy state name reading.</li>
</ul>
<p><strong>Insights You Gain</strong>:</p>
<ul>
<li><strong>Geographical Sales Leaders:</strong> See which states drive the most sales.</li>
<li><strong>Regional Variations:</strong> Spot high-performing and underperforming regions at a glance.</li>
<li><strong>Interactive Details (Map):</strong> Hover over states for precise sales figures.</li>
</ul>
<h5 id="heading-sales-data-by-category">Sales Data by Category</h5>
<p>This will help you make smarter inventory and shipping decisions. Let's analyze how your categories, sub-categories, and shipping choices impact sales.</p>
<p><strong>Prerequisites:</strong></p>
<ul>
<li>You have a pandas DataFrame named <code>df</code>.</li>
<li>It contains columns named 'Category', 'Sub-Category', 'Ship Mode', and 'Sales'.</li>
</ul>
<p><strong>Step 1: Import Plotly Express</strong></p>
<pre><code class="lang-python"><span class="hljs-keyword">import</span> plotly.express <span class="hljs-keyword">as</span> px
</code></pre>
<p><strong>Explanation:</strong>  </p>
<ul>
<li>We use Plotly Express for its high-level functions that streamline complex visualization creation.</li>
</ul>
<p><strong>Step 2: Prepare Data for Pie Chart</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Summarize sales by Category and Sub-Category</span>
df_summary = df.groupby([<span class="hljs-string">'Category'</span>, <span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We group by both 'Category' and 'Sub-Category', summing 'Sales' to get total sales for each combination.</li>
</ul>
<p><strong>Step 3: Create a Nested Pie Chart</strong></p>
<pre><code class="lang-python">fig = px.sunburst(df_summary, path=[<span class="hljs-string">'Category'</span>, <span class="hljs-string">'Sub-Category'</span>], values=<span class="hljs-string">'Sales'</span>)
fig.show()
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>px.sunburst</code> creates a hierarchical pie chart where the outer ring represents categories and inner slices represent sub-categories.</li>
<li><code>path</code> specifies the hierarchical structure.</li>
<li><code>values</code> determines the size of each slice based on sales contribution.</li>
</ul>
<p><strong>Step 4: Prepare Data for Treemap</strong></p>
<pre><code class="lang-python"><span class="hljs-comment"># Summarize sales (with Ship Mode)</span>
df_summary = df.groupby([<span class="hljs-string">'Category'</span>, <span class="hljs-string">'Ship Mode'</span>, <span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li>We expand the grouping to include 'Ship Mode', calculating sales at an even more granular level.</li>
</ul>
<p><strong>Step 5: Create a Treemap</strong></p>
<pre><code class="lang-python">fig = px.treemap(df_summary, path=[<span class="hljs-string">'Category'</span>, <span class="hljs-string">'Ship Mode'</span>, <span class="hljs-string">'Sub-Category'</span>], values=<span class="hljs-string">'Sales'</span>)
fig.show()
</code></pre>
<p><strong>Explanation:</strong></p>
<ul>
<li><code>px.treemap</code> creates a visualization where rectangles represent hierarchical data.</li>
<li>Larger rectangles denote higher sales.</li>
<li>This lets you compare sales performance across different category/sub-category/shipping method combinations.</li>
</ul>
<p><strong>Insights You Gain</strong>:</p>
<p><strong>Nested Pie Chart</strong></p>
<ul>
<li>Dominant categories and their top-selling sub-categories.</li>
<li>Relative sales contribution of each sub-category within a broader category.</li>
</ul>
<p><strong>Treemap</strong></p>
<ul>
<li>Sales performance within category/sub-category/shipping method combinations.</li>
<li>Quickly spot the most profitable combinations.</li>
</ul>
<p><strong>Benefits of Using Plotly Express</strong></p>
<ul>
<li><strong>Interactive visualizations:</strong> Hover for details, zoom, explore the data.</li>
<li><strong>Concise code:</strong> Create complex visuals with minimal code.</li>
</ul>
<h3 id="heading-full-code-3">Full Code:</h3>
<p>Here is the full code we have written:</p>
<pre><code class="lang-python"><span class="hljs-comment"># importation of python libraries</span>

<span class="hljs-keyword">import</span> pandas <span class="hljs-keyword">as</span> pd
<span class="hljs-keyword">import</span> numpy <span class="hljs-keyword">as</span> np
<span class="hljs-keyword">import</span> matplotlib.pyplot <span class="hljs-keyword">as</span> plt
<span class="hljs-keyword">import</span> seaborn <span class="hljs-keyword">as</span> sns



<span class="hljs-keyword">from</span> google.colab <span class="hljs-keyword">import</span> drive
drive.mount(<span class="hljs-string">'/content/drive'</span>)

df = pd.read_csv(<span class="hljs-string">r"/content/sample_data/train.csv"</span>)

df.head()

df.info()

<span class="hljs-comment"># calculating number of null values in column postal code</span>

null_count = df[<span class="hljs-string">'Postal Code'</span>].isnull().sum()
print(null_count)

<span class="hljs-comment"># filling null values</span>
df[<span class="hljs-string">"Postal Code"</span>].fillna(<span class="hljs-number">0</span>, inplace = <span class="hljs-literal">True</span>)

df[<span class="hljs-string">'Postal Code'</span>] = df[<span class="hljs-string">'Postal Code'</span>].astype(int)

df.info()

df.describe()

<span class="hljs-comment">### Checking for duplicates</span>

<span class="hljs-keyword">if</span> df.duplicated().sum() &gt; <span class="hljs-number">0</span>:  <span class="hljs-comment">#</span>
    print(<span class="hljs-string">"Duplicates exist in the DataFrame."</span>)
<span class="hljs-keyword">else</span>:
    print(<span class="hljs-string">"No duplicates found in the DataFrame."</span>)

<span class="hljs-comment"># Exploratory Data Analysis</span>
<span class="hljs-comment">## Customer Analysis</span>

df.head(<span class="hljs-number">3</span>)

<span class="hljs-comment">### Customer segmentation</span>

- Group customers based on segments

<span class="hljs-comment"># Types of customers</span>

types_of_customers = df[<span class="hljs-string">'Segment'</span>].unique()
print(types_of_customers)

<span class="hljs-comment"># Count unique values in 'Segment' and reset the index to turn them into a column</span>
number_of_customers = df[<span class="hljs-string">'Segment'</span>].value_counts().reset_index()

<span class="hljs-comment"># Correct the renaming of columns based on your requirements</span>
number_of_customers = number_of_customers.rename(columns={<span class="hljs-string">'Segment'</span>: <span class="hljs-string">'Total Customers'</span>})

<span class="hljs-comment"># Print the renamed DataFrame to confirm correct renaming</span>
print(number_of_customers.head())

plt.pie(number_of_customers[<span class="hljs-string">'count'</span>], labels=number_of_customers[<span class="hljs-string">'Total Customers'</span>], autopct=<span class="hljs-string">'%1.1f%%'</span>)

<span class="hljs-comment"># Set the title of the pie chart</span>
plt.title(<span class="hljs-string">'Distribution of Clients'</span>)
plt.show()
print(number_of_customers.columns)

<span class="hljs-comment"># Customers and Sales</span>

<span class="hljs-comment"># Group the data by the "Segment" column and calculate the total sales for each segment</span>

sales_per_segment = df.groupby(<span class="hljs-string">'Segment'</span>)[<span class="hljs-string">'Sales'</span>].sum().reset_index()
sales_per_segment = sales_per_segment.rename(columns={<span class="hljs-string">'Segment'</span>: <span class="hljs-string">'Customer Type'</span>, <span class="hljs-string">'Sales'</span>: <span class="hljs-string">'Total Sales'</span>})

print(sales_per_segment)

<span class="hljs-comment"># Ploting a bar graph</span>

plt.bar(sales_per_segment[<span class="hljs-string">'Customer Type'</span>], sales_per_segment[<span class="hljs-string">'Total Sales'</span>])

<span class="hljs-comment"># Labels</span>
plt.title(<span class="hljs-string">'Sales per Customer Category'</span>)
plt.xlabel(<span class="hljs-string">'Customer Type'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)

plt.show()


plt.pie(sales_per_segment[<span class="hljs-string">'Total Sales'</span>], labels=sales_per_segment[<span class="hljs-string">'Customer Type'</span>], autopct=<span class="hljs-string">'%1.1f%%'</span>)

<span class="hljs-comment"># Set the title of the pie chart</span>
plt.title(<span class="hljs-string">'Sales per Customer Category'</span>)
plt.show()

<span class="hljs-comment"># Number of customers in each segment</span>

customer_segmentation = df[<span class="hljs-string">'Segment'</span>].value_counts().reset_index()
customer_segmentation = customer_segmentation.rename(columns={<span class="hljs-string">'index'</span>: <span class="hljs-string">'Customer Type'</span>, <span class="hljs-string">'Segment'</span>: <span class="hljs-string">'Total Customers'</span>})

<span class="hljs-comment"># customer_segmentation = df['Segment'].value_counts().reset_index().rename(columns={'index': 'Customer Type', 'Segment': 'Total Customers'})</span>

print(customer_segmentation)

**Customer Loyalty**
- Examine the repeat purchase behavior of customers



df.head(<span class="hljs-number">2</span>)

<span class="hljs-comment"># Group the data by Customer ID, Customer Name, Segments, and calculate the frequency of orders for each customer</span>
customer_order_frequency = df.groupby([<span class="hljs-string">'Customer ID'</span>, <span class="hljs-string">'Customer Name'</span>, <span class="hljs-string">'Segment'</span>])[<span class="hljs-string">'Order ID'</span>].count().reset_index()

<span class="hljs-comment"># Rename the column to represent the frequency of orders</span>
customer_order_frequency.rename(columns={<span class="hljs-string">'Order ID'</span>: <span class="hljs-string">'Total Orders'</span>}, inplace=<span class="hljs-literal">True</span>)

<span class="hljs-comment"># Identify repeat customers (customers with order frequency greater than 1)</span>
repeat_customers = customer_order_frequency[customer_order_frequency[<span class="hljs-string">'Total Orders'</span>] &gt;= <span class="hljs-number">1</span>]

<span class="hljs-comment"># Sort "repeat_customers" in descending order based on the "Order Frequency" column</span>
repeat_customers_sorted = repeat_customers.sort_values(by=<span class="hljs-string">'Total Orders'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Print the result- the first 10 and reset index</span>
print(repeat_customers_sorted.head(<span class="hljs-number">12</span>).reset_index(drop=<span class="hljs-literal">True</span>))

<span class="hljs-comment">### Sales by Customer</span>
- Identify top-spending customers based on their total purchase amount

<span class="hljs-comment"># Group the data by customer IDs and calculate the total purchase (sales) for each customer</span>
customer_sales = df.groupby([<span class="hljs-string">'Customer ID'</span>, <span class="hljs-string">'Customer Name'</span>, <span class="hljs-string">'Segment'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

<span class="hljs-comment"># Sort the customers based on their total purchase in descending order to identify top spenders</span>
top_spenders = customer_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Print the top-spending customers</span>
print(top_spenders.head(<span class="hljs-number">10</span>).reset_index(drop=<span class="hljs-literal">True</span>))

<span class="hljs-comment">### Shipping</span>

<span class="hljs-comment"># Types of Shipping methods</span>

types_of_customers = df[<span class="hljs-string">'Ship Mode'</span>].unique()
print(types_of_customers)

df.head(<span class="hljs-number">2</span>)

<span class="hljs-comment"># Frequency of use of a shipping methods</span>

shipping_model = df[<span class="hljs-string">'Ship Mode'</span>].value_counts().reset_index()
shipping_model = shipping_model.rename(columns={<span class="hljs-string">'index'</span>:<span class="hljs-string">'Use Frequency'</span>, <span class="hljs-string">'Ship Mode'</span>: <span class="hljs-string">'Mode of Shipment'</span>, <span class="hljs-string">'count'</span> : <span class="hljs-string">'Use Frequency'</span>})

print(shipping_model)


<span class="hljs-comment"># Plotting a Pie chart</span>

plt.pie(shipping_model[<span class="hljs-string">'Use Frequency'</span>], labels=shipping_model[<span class="hljs-string">'Mode of Shipment'</span>], autopct=<span class="hljs-string">'%1.1f%%'</span>)

<span class="hljs-comment"># Set the title of the pie chart</span>
plt.title(<span class="hljs-string">'Popular Mode Of Shipment'</span>)
plt.show()


<span class="hljs-comment">### Geographical Analysis</span>

<span class="hljs-comment"># Customers per state</span>

state = df[<span class="hljs-string">'State'</span>].value_counts().reset_index()
state = state.rename(columns={<span class="hljs-string">'index'</span>:<span class="hljs-string">'State'</span>, <span class="hljs-string">'State'</span>:<span class="hljs-string">'Number_of_customers'</span>})

print(state.head(<span class="hljs-number">20</span>))

<span class="hljs-comment"># Customers per city</span>

city = df[<span class="hljs-string">'City'</span>].value_counts().reset_index()
city= city.rename(columns={<span class="hljs-string">'index'</span>:<span class="hljs-string">'City'</span>, <span class="hljs-string">'City'</span>:<span class="hljs-string">'Number_of_customers'</span>})

print(city.head(<span class="hljs-number">15</span>))

<span class="hljs-comment"># Sales per state</span>

<span class="hljs-comment"># Group the data by state and calculate the total purchases (sales) for each state</span>
state_sales = df.groupby([<span class="hljs-string">'State'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

<span class="hljs-comment"># Sort the states based on their total sales in descending order to identify top spenders</span>
top_sales = state_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Print the states</span>
print(top_sales.head(<span class="hljs-number">20</span>).reset_index(drop=<span class="hljs-literal">True</span>))

<span class="hljs-comment"># Group the data by state and calculate the total purchase (sales) for each city</span>
city_sales = df.groupby([<span class="hljs-string">'City'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

<span class="hljs-comment"># Sort the cities based on their sales in descending order to identify top cities</span>
top_city_sales = city_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Print the states</span>
print(top_city_sales.head(<span class="hljs-number">20</span>).reset_index(drop=<span class="hljs-literal">True</span>))

state_city_sales = df.groupby([<span class="hljs-string">'State'</span>,<span class="hljs-string">'City'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

print(state_city_sales.head(<span class="hljs-number">20</span>))
</code></pre>
<h1 id="heading-this-is-formatted-as-code">This is formatted as code</h1>
<pre><code>
## Product Analysis

### Product Category Analysis

- Investigate the sales performance <span class="hljs-keyword">of</span> different product

# Types <span class="hljs-keyword">of</span> products <span class="hljs-keyword">in</span> the Stores

products = df[<span class="hljs-string">'Category'</span>].unique()
print(products)

product_subcategory = df[<span class="hljs-string">'Sub-Category'</span>].unique()
print(product_subcategory)

# Types <span class="hljs-keyword">of</span> sub category

product_subcategory = df[<span class="hljs-string">'Sub-Category'</span>].nunique()
print(product_subcategory)

# Group the data by product category and how many sub-category it has
subcategory_count = df.groupby(<span class="hljs-string">'Category'</span>)[<span class="hljs-string">'Sub-Category'</span>].nunique().reset_index()
# sort by ascending order
subcategory_count = subcategory_count.sort_values(by=<span class="hljs-string">'Sub-Category'</span>, ascending=False)
# Print the states
print(subcategory_count)

subcategory_count_sales = df.groupby([<span class="hljs-string">'Category'</span>,<span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

print(subcategory_count_sales)

# Group the data by product category versus the sales <span class="hljs-keyword">from</span> each product category
product_category = df.groupby([<span class="hljs-string">'Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

# Sort the product category <span class="hljs-keyword">in</span> their descending order and identify top product category
top_product_category = product_category.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=False)

# Print the states
print(top_product_category.reset_index(drop=True))

# Plotting a pie chart
plt.pie(top_product_category[<span class="hljs-string">'Sales'</span>], labels=top_product_category[<span class="hljs-string">'Category'</span>], autopct=<span class="hljs-string">'%1.1f%%'</span>)

# set the labels <span class="hljs-keyword">of</span> the pie chart
plt.title(<span class="hljs-string">'Top Product Categories Based on Sales'</span>)

plt.show()


# Group the data by product sub category versus the sales
product_subcategory = df.groupby([<span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

# Sort the product category <span class="hljs-keyword">in</span> their descending order and identify top product category
top_product_subcategory = product_subcategory.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=False)

# Print the states
print(top_product_subcategory.reset_index(drop=True))


top_product_subcategory = top_product_subcategory.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=True)

# Ploting a bar graph

plt.barh(top_product_subcategory[<span class="hljs-string">'Sub-Category'</span>], top_product_subcategory[<span class="hljs-string">'Sales'</span>])

# Labels
plt.title(<span class="hljs-string">'Top Product Categories Based on Sales'</span>)
plt.xlabel(<span class="hljs-string">'Product Sub-Category'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.xticks(rotation=<span class="hljs-number">0</span>)

plt.show()


## Sales

# Convert the <span class="hljs-string">"Order Date"</span> column to datetime format

df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>], dayfirst=True)

# Group the data by years and calculate the total sales amount <span class="hljs-keyword">for</span> each year
yearly_sales = df.groupby(df[<span class="hljs-string">'Order Date'</span>].dt.year)[<span class="hljs-string">'Sales'</span>].sum()

yearly_sales = yearly_sales.reset_index()
yearly_sales = yearly_sales.rename(columns={<span class="hljs-string">'Order Date'</span>: <span class="hljs-string">'Year'</span>, <span class="hljs-string">'Sales'</span>:<span class="hljs-string">'Total Sales'</span>})

# yearly_sales =
# Print the total sales <span class="hljs-keyword">for</span> each year
print(yearly_sales)

# Ploting a bar graph

plt.bar(yearly_sales[<span class="hljs-string">'Year'</span>], yearly_sales[<span class="hljs-string">'Total Sales'</span>])

# Labels
plt.title(<span class="hljs-string">'Yearly Sales'</span>)
plt.xlabel(<span class="hljs-string">'Year'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.xticks(rotation=<span class="hljs-number">45</span>)

plt.show()


# Create a line graph <span class="hljs-keyword">for</span> total sales by year
plt.plot(yearly_sales[<span class="hljs-string">'Year'</span>], yearly_sales[<span class="hljs-string">'Total Sales'</span>], marker=<span class="hljs-string">'o'</span>, linestyle=<span class="hljs-string">'-'</span>)
plt.xlabel(<span class="hljs-string">'Year'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.title(<span class="hljs-string">'Total Sales by Year'</span>)

# Display the plot
plt.tight_layout()

plt.show()

# Convert the <span class="hljs-string">"Order Date"</span> column to datetime format
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>], dayfirst=True)

# Filter the data <span class="hljs-keyword">for</span> the year <span class="hljs-number">2018</span>
year_sales = df[df[<span class="hljs-string">'Order Date'</span>].dt.year == <span class="hljs-number">2018</span>]

# Calculate the quarterly sales <span class="hljs-keyword">for</span> <span class="hljs-number">2018</span>
quarterly_sales = year_sales.resample(<span class="hljs-string">'Q'</span>, on=<span class="hljs-string">'Order Date'</span>)[<span class="hljs-string">'Sales'</span>].sum()

quarterly_sales = quarterly_sales.reset_index()
quarterly_sales = quarterly_sales.rename(columns={<span class="hljs-string">'Order Date'</span>: <span class="hljs-string">'Quarter'</span>, <span class="hljs-string">'Sales'</span>:<span class="hljs-string">'Total Sales'</span>})


print(<span class="hljs-string">"Quarterly Sales for 2018:"</span>)
print(quarterly_sales)

# Create a line graph <span class="hljs-keyword">for</span> total sales by year
plt.plot(quarterly_sales[<span class="hljs-string">'Quarter'</span>], quarterly_sales[<span class="hljs-string">'Total Sales'</span>], marker=<span class="hljs-string">'o'</span>, linestyle=<span class="hljs-string">'--'</span>)

plt.xlabel(<span class="hljs-string">'Year'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.title(<span class="hljs-string">'Total Sales by Year'</span>)

# Display the plot
plt.tight_layout()
plt.xticks(rotation=<span class="hljs-number">75</span>)

plt.show()

# Convert the <span class="hljs-string">"Order Date"</span> column to datetime format
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>], dayfirst=True)

# Filter the data <span class="hljs-keyword">for</span> the year <span class="hljs-number">2018</span>
year_sales = df[df[<span class="hljs-string">'Order Date'</span>].dt.year == <span class="hljs-number">2018</span>]

# Calculate the monthly sales <span class="hljs-keyword">for</span> <span class="hljs-number">2018</span>
monthly_sales = year_sales.resample(<span class="hljs-string">'M'</span>, on=<span class="hljs-string">'Order Date'</span>)[<span class="hljs-string">'Sales'</span>].sum()

# Renaming the columns
monthly_sales = monthly_sales.reset_index()
monthly_sales = monthly_sales.rename(columns={<span class="hljs-string">'Order Date'</span>:<span class="hljs-string">'Month'</span>, <span class="hljs-string">'Sales'</span>:<span class="hljs-string">'Total Montly Sales'</span>})

# Print the monthly and quarterly sales <span class="hljs-keyword">for</span> <span class="hljs-number">2018</span>
print(<span class="hljs-string">"Monthly Sales for 2018:"</span>)
print(monthly_sales)


# Create a line graph <span class="hljs-keyword">for</span> total sales by year
plt.plot(monthly_sales[<span class="hljs-string">'Month'</span>], monthly_sales[<span class="hljs-string">'Total Montly Sales'</span>], marker=<span class="hljs-string">'o'</span>, linestyle=<span class="hljs-string">'--'</span>)

plt.xlabel(<span class="hljs-string">'Year'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.title(<span class="hljs-string">'Total Sales by Month'</span>)

# Display the plot
plt.tight_layout()
plt.xticks(rotation=<span class="hljs-number">75</span>)

plt.show()

## Sales Trends

# Convert the <span class="hljs-string">"Order Date"</span> column to datetime format
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>], dayfirst=True)

# Group the data by months and calculate the total sales amount <span class="hljs-keyword">for</span> each month
monthly_sales = df.groupby(df[<span class="hljs-string">'Order Date'</span>].dt.to_period(<span class="hljs-string">'M'</span>))[<span class="hljs-string">'Sales'</span>].sum()

# Plot the sales trends <span class="hljs-keyword">for</span> months
plt.figure(figsize=(<span class="hljs-number">12</span>, <span class="hljs-number">26</span>))

# Monthly Sales Trend
plt.subplot(<span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">1</span>)
monthly_sales.plot(kind=<span class="hljs-string">'line'</span>, marker=<span class="hljs-string">'o'</span>)
plt.title(<span class="hljs-string">'Monthly Sales Trend'</span>)
plt.xlabel(<span class="hljs-string">'Month'</span>)
plt.ylabel(<span class="hljs-string">'Sales Amount'</span>)

# Adjust layout and display the plots
# plt.tight_layout()
plt.show()

# Assuming you have a DataFrame named <span class="hljs-string">"df"</span> <span class="hljs-keyword">with</span> columns <span class="hljs-string">"Order Date"</span> and <span class="hljs-string">"Sales amount"</span>

# Convert the <span class="hljs-string">"Order Date"</span> column to datetime format
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>], dayfirst=True)

# Group the data by quarters and calculate the total sales amount <span class="hljs-keyword">for</span> each quarter
quarterly_sales = df.groupby(df[<span class="hljs-string">'Order Date'</span>].dt.to_period(<span class="hljs-string">'Q'</span>))[<span class="hljs-string">'Sales'</span>].sum()

# Plot the sales trends <span class="hljs-keyword">for</span> months, quarters, and years
plt.figure(figsize=(<span class="hljs-number">12</span>, <span class="hljs-number">20</span>))

# Quarterly Sales Trend
plt.subplot(<span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>)
quarterly_sales.plot(kind=<span class="hljs-string">'line'</span>, marker=<span class="hljs-string">'o'</span>)
plt.title(<span class="hljs-string">'Quarterly Sales Trend'</span>)
plt.xlabel(<span class="hljs-string">'Quarter'</span>)
plt.ylabel(<span class="hljs-string">'Sales Amount'</span>)

# Adjust layout and display the plots
#plt.tight_layout()
plt.show()

# Assuming you have a DataFrame named <span class="hljs-string">"df"</span> <span class="hljs-keyword">with</span> columns <span class="hljs-string">"Order Date"</span> and <span class="hljs-string">"Sales amount"</span>

# Convert the <span class="hljs-string">"Order Date"</span> column to datetime format
df[<span class="hljs-string">'Order Date'</span>] = pd.to_datetime(df[<span class="hljs-string">'Order Date'</span>], dayfirst=True)

# Group the data by years and calculate the total sales amount <span class="hljs-keyword">for</span> each year
yearly_sales = df.groupby(df[<span class="hljs-string">'Order Date'</span>].dt.to_period(<span class="hljs-string">'Y'</span>))[<span class="hljs-string">'Sales'</span>].sum()

# Plot the sales trends <span class="hljs-keyword">for</span> quarters
plt.figure(figsize=(<span class="hljs-number">12</span>, <span class="hljs-number">26</span>))

# Yearly Sales Trend
plt.subplot(<span class="hljs-number">3</span>, <span class="hljs-number">1</span>, <span class="hljs-number">3</span>)
yearly_sales.plot(kind=<span class="hljs-string">'line'</span>, marker=<span class="hljs-string">'o'</span>)
plt.title(<span class="hljs-string">'Yearly Sales Trend'</span>)
plt.xlabel(<span class="hljs-string">'Year'</span>)
plt.ylabel(<span class="hljs-string">'Sales Amount'</span>)

# Adjust layout and display the plots

plt.show()

# Group by <span class="hljs-string">"Order Date"</span> and calculate the sum <span class="hljs-keyword">of</span> sales
df_summary = df.groupby(<span class="hljs-string">'Order Date'</span>)[<span class="hljs-string">'Sales'</span>].sum().reset_index()

# Create a line plot
plt.figure(figsize=(<span class="hljs-number">30</span>, <span class="hljs-number">8</span>))
plt.plot(df_summary[<span class="hljs-string">'Order Date'</span>], df_summary[<span class="hljs-string">'Sales'</span>], marker=<span class="hljs-string">'o'</span>, linestyle=<span class="hljs-string">'-'</span>)
plt.xlabel(<span class="hljs-string">'Order Date'</span>)
plt.ylabel(<span class="hljs-string">'Sales'</span>)
plt.title(<span class="hljs-string">'Sales Over Time'</span>)
plt.grid(True)
plt.show()

<span class="hljs-keyword">import</span> plotly.graph_objects <span class="hljs-keyword">as</span> go
<span class="hljs-keyword">from</span> plotly.subplots <span class="hljs-keyword">import</span> make_subplots

# Initialize Plotly <span class="hljs-keyword">in</span> Jupyter Notebook mode
<span class="hljs-keyword">import</span> plotly.io <span class="hljs-keyword">as</span> pio

# Create a mapping <span class="hljs-keyword">for</span> all <span class="hljs-number">50</span> states
all_state_mapping = {
    <span class="hljs-string">"Alabama"</span>: <span class="hljs-string">"AL"</span>, <span class="hljs-string">"Alaska"</span>: <span class="hljs-string">"AK"</span>, <span class="hljs-string">"Arizona"</span>: <span class="hljs-string">"AZ"</span>, <span class="hljs-string">"Arkansas"</span>: <span class="hljs-string">"AR"</span>,
    <span class="hljs-string">"California"</span>: <span class="hljs-string">"CA"</span>, <span class="hljs-string">"Colorado"</span>: <span class="hljs-string">"CO"</span>, <span class="hljs-string">"Connecticut"</span>: <span class="hljs-string">"CT"</span>, <span class="hljs-string">"Delaware"</span>: <span class="hljs-string">"DE"</span>,
    <span class="hljs-string">"Florida"</span>: <span class="hljs-string">"FL"</span>, <span class="hljs-string">"Georgia"</span>: <span class="hljs-string">"GA"</span>, <span class="hljs-string">"Hawaii"</span>: <span class="hljs-string">"HI"</span>, <span class="hljs-string">"Idaho"</span>: <span class="hljs-string">"ID"</span>, <span class="hljs-string">"Illinois"</span>: <span class="hljs-string">"IL"</span>,
    <span class="hljs-string">"Indiana"</span>: <span class="hljs-string">"IN"</span>, <span class="hljs-string">"Iowa"</span>: <span class="hljs-string">"IA"</span>, <span class="hljs-string">"Kansas"</span>: <span class="hljs-string">"KS"</span>, <span class="hljs-string">"Kentucky"</span>: <span class="hljs-string">"KY"</span>, <span class="hljs-string">"Louisiana"</span>: <span class="hljs-string">"LA"</span>,
    <span class="hljs-string">"Maine"</span>: <span class="hljs-string">"ME"</span>, <span class="hljs-string">"Maryland"</span>: <span class="hljs-string">"MD"</span>, <span class="hljs-string">"Massachusetts"</span>: <span class="hljs-string">"MA"</span>, <span class="hljs-string">"Michigan"</span>: <span class="hljs-string">"MI"</span>, <span class="hljs-string">"Minnesota"</span>: <span class="hljs-string">"MN"</span>,
    <span class="hljs-string">"Mississippi"</span>: <span class="hljs-string">"MS"</span>, <span class="hljs-string">"Missouri"</span>: <span class="hljs-string">"MO"</span>, <span class="hljs-string">"Montana"</span>: <span class="hljs-string">"MT"</span>, <span class="hljs-string">"Nebraska"</span>: <span class="hljs-string">"NE"</span>, <span class="hljs-string">"Nevada"</span>: <span class="hljs-string">"NV"</span>,
    <span class="hljs-string">"New Hampshire"</span>: <span class="hljs-string">"NH"</span>, <span class="hljs-string">"New Jersey"</span>: <span class="hljs-string">"NJ"</span>, <span class="hljs-string">"New Mexico"</span>: <span class="hljs-string">"NM"</span>, <span class="hljs-string">"New York"</span>: <span class="hljs-string">"NY"</span>,
    <span class="hljs-string">"North Carolina"</span>: <span class="hljs-string">"NC"</span>, <span class="hljs-string">"North Dakota"</span>: <span class="hljs-string">"ND"</span>, <span class="hljs-string">"Ohio"</span>: <span class="hljs-string">"OH"</span>, <span class="hljs-string">"Oklahoma"</span>: <span class="hljs-string">"OK"</span>,
    <span class="hljs-string">"Oregon"</span>: <span class="hljs-string">"OR"</span>, <span class="hljs-string">"Pennsylvania"</span>: <span class="hljs-string">"PA"</span>, <span class="hljs-string">"Rhode Island"</span>: <span class="hljs-string">"RI"</span>, <span class="hljs-string">"South Carolina"</span>: <span class="hljs-string">"SC"</span>,
    <span class="hljs-string">"South Dakota"</span>: <span class="hljs-string">"SD"</span>, <span class="hljs-string">"Tennessee"</span>: <span class="hljs-string">"TN"</span>, <span class="hljs-string">"Texas"</span>: <span class="hljs-string">"TX"</span>, <span class="hljs-string">"Utah"</span>: <span class="hljs-string">"UT"</span>, <span class="hljs-string">"Vermont"</span>: <span class="hljs-string">"VT"</span>,
    <span class="hljs-string">"Virginia"</span>: <span class="hljs-string">"VA"</span>, <span class="hljs-string">"Washington"</span>: <span class="hljs-string">"WA"</span>, <span class="hljs-string">"West Virginia"</span>: <span class="hljs-string">"WV"</span>, <span class="hljs-string">"Wisconsin"</span>: <span class="hljs-string">"WI"</span>, <span class="hljs-string">"Wyoming"</span>: <span class="hljs-string">"WY"</span>
}

# Add the Abbreviation column to the DataFrame
df[<span class="hljs-string">'Abbreviation'</span>] = df[<span class="hljs-string">'State'</span>].map(all_state_mapping)

# Group by state and calculate the sum <span class="hljs-keyword">of</span> sales
sum_of_sales = df.groupby(<span class="hljs-string">'State'</span>)[<span class="hljs-string">'Sales'</span>].sum().reset_index()

# Add Abbreviation to sum_of_sales
sum_of_sales[<span class="hljs-string">'Abbreviation'</span>] = sum_of_sales[<span class="hljs-string">'State'</span>].map(all_state_mapping)

# Create a choropleth map using Plotly
fig = go.Figure(data=go.Choropleth(
    locations=sum_of_sales[<span class="hljs-string">'Abbreviation'</span>],
    locationmode=<span class="hljs-string">'USA-states'</span>,
    z=sum_of_sales[<span class="hljs-string">'Sales'</span>],
    hoverinfo=<span class="hljs-string">'location+z'</span>,
    showscale=True
))

fig.update_geos(projection_type=<span class="hljs-string">"albers usa"</span>)
fig.update_layout(
    geo_scope=<span class="hljs-string">'usa'</span>,
    title=<span class="hljs-string">'Total Sales by U.S. State'</span>
)

fig.show()

# Group by state and calculaye the sum <span class="hljs-keyword">of</span> sales
sum_of_sales = df.groupby(<span class="hljs-string">'State'</span>)[<span class="hljs-string">'Sales'</span>].sum().reset_index()

# Sort the DataFrame by the <span class="hljs-string">'Sales'</span> column <span class="hljs-keyword">in</span> descending order
sum_of_sales = sum_of_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=False)

# Create a horinzontal bar graph
plt.figure(figsize=(<span class="hljs-number">10</span>, <span class="hljs-number">13</span>))
ax = sns.barplot(x=<span class="hljs-string">'Sales'</span>, y=<span class="hljs-string">'State'</span>, data=sum_of_sales, errorbar=None)

plt.xlabel(<span class="hljs-string">'Sales'</span>)
plt.ylabel(<span class="hljs-string">'State'</span>)
plt.title(<span class="hljs-string">'Total Sales by State'</span>)
plt.show()

<span class="hljs-keyword">import</span> plotly.express <span class="hljs-keyword">as</span> px

# Summarize the Sales data by Category and Sub-Category
df_summary = df.groupby([<span class="hljs-string">'Category'</span>, <span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

# Create a nested pie chart
fig = px.sunburst(
    df_summary, path=[<span class="hljs-string">'Category'</span>, <span class="hljs-string">'Sub-Category'</span>], values=<span class="hljs-string">'Sales'</span>)

fig.show()

# Summarize the Sales data by Category, Ship Mode and Sub-Category
df_summary = df.groupby([<span class="hljs-string">'Category'</span>, <span class="hljs-string">'Ship Mode'</span>, <span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

#Create a treemap
fig = px.treemap(df_summary, path=[<span class="hljs-string">'Category'</span>, <span class="hljs-string">'Ship Mode'</span>, <span class="hljs-string">'Sub-Category'</span>], values=<span class="hljs-string">'Sales'</span>)

fig.show()
</code></pre><h3 id="heading-analyzing-the-results">Analyzing The Results</h3>
<h4 id="heading-customer-segmentation-1">Customer Segmentation</h4>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-18.png" alt="Image" width="600" height="400" loading="lazy">
<em>Distribution of Clients - Consumer, Corporate, Home Office</em></p>
<h4 id="heading-understanding-the-distribution-and-impact-of-customer-segments">Understanding the Distribution and Impact of Customer Segments</h4>
<p>The analysis of our SuperStore dataset highlights a pivotal aspect of business strategy—customer segmentation. </p>
<p>As you can see in the "Distribution of Clients" pie chart above, our customers are divided into three primary categories: Consumer (52.1%), Corporate (30.1%), and Home Office (17.8%). These segments reveal the diversity within our customer base and underscore the need for tailored marketing strategies.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-19.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sales per Customer Category</em></p>
<h4 id="heading-aligning-sales-focus-with-customer-segmentation">Aligning Sales Focus with Customer Segmentation</h4>
<p>If we explore further into the "Sales per Customer Category" data, we'll find a compelling story. While consumers make up over half of our customer base, they contribute to 50.8% of total sales, closely aligning with their distribution.</p>
<p>Conversely, corporate clients, though only 30.1% of our base, account for a substantial 30.4% of sales. </p>
<p>Home office clients, despite being the smallest segment, contribute 18.8% of sales, indicating a higher purchase value per transaction compared to their overall presence.</p>
<h3 id="heading-strategic-marketing-action-plan-with-targeted-initiatives">Strategic Marketing Action Plan with Targeted Initiatives</h3>
<p>Because our consumer base is very diverse, and each segment demonstrates distinct purchasing behaviors, this means we'll need to create a tailored marketing approach to maximize sales and profitability. </p>
<p>This strategic plan aims to address the unique needs and preferences of each segment while driving overall business growth.</p>
<h4 id="heading-create-segment-specific-marketing-campaigns">Create Segment-Specific Marketing Campaigns</h4>
<ol>
<li><strong>Consumer Segment (Majority):</strong></li>
</ol>
<p>Consumers represent the largest segment, offering the greatest potential for high-volume sales through broad-reaching campaigns.</p>
<p><strong>Objective:</strong> Capture mass market attention and drive high-volume sales.</p>
<p><strong>Tactics:</strong></p>
<ul>
<li><strong>Multi-Channel Campaigns:</strong> Utilize TV, radio, print, online advertising, and social media to reach a wide audience.</li>
<li><strong>Seasonal Promotions:</strong> Capitalize on holidays and special events with themed campaigns and limited-time offers.</li>
<li><strong>Influencer Marketing:</strong> Partner with popular figures for engaging content to create brand awareness and drive conversions.</li>
<li><p><strong>Referral Programs:</strong> Encourage word-of-mouth marketing by offering incentives for customer referrals, leveraging their strong presence.</p>
</li>
<li><p><strong>Corporate Clients:</strong></p>
</li>
</ul>
<p>Corporate clients, while a smaller segment, contribute significantly to sales, indicating a higher average order value and the potential for long-term partnerships.</p>
<p><strong>Objective:</strong> Position as a trusted partner offering scalable, tailored solutions for businesses.</p>
<p><strong>Tactics:</strong></p>
<ul>
<li><strong>Content Marketing:</strong> Publish whitepapers, case studies, and thought leadership articles showcasing industry expertise and building credibility.</li>
<li><strong>Account-Based Marketing (ABM):</strong> Develop personalized campaigns for high-value accounts, focusing on building relationships and addressing specific pain points.</li>
<li><strong>Webinars and Workshops:</strong> Host educational events showcasing products and services tailored for business needs, emphasizing scalability and customization.</li>
<li><p><strong>Trade Shows and Conferences:</strong> Network with potential clients and demonstrate solutions in a professional setting, establishing direct relationships.</p>
</li>
<li><p><strong>Home Office Professionals:</strong></p>
</li>
</ul>
<p>Despite being the smallest segment, home office professionals demonstrate a higher purchase value per transaction, indicating a willingness to invest in premium products and services.</p>
<p><strong>Objective:</strong> Cultivate a premium brand image for remote workers and freelancers.</p>
<p><strong>Tactics:</strong></p>
<ul>
<li><strong>Targeted Email Marketing:</strong> Send personalized offers based on browsing/purchase history, catering to individual needs and preferences.</li>
<li><strong>Social Media Engagement:</strong> Foster community in targeted groups, offering tips and resources to build a loyal following and establish thought leadership.</li>
<li><strong>Affiliate Marketing:</strong> Partner with relevant blogs and websites to promote products and services, reaching a targeted audience of home office professionals.</li>
<li><strong>Premium Subscription Service:</strong> Offer exclusive discounts, early access, and personalized support to enhance the value proposition for this discerning segment.</li>
</ul>
<h4 id="heading-optimized-product-offerings">Optimized Product Offerings</h4>
<ul>
<li><strong>Action:</strong> Analyze sales data, feedback, and trends.</li>
<li><strong>Outcome:</strong> Tailored product assortments and strategic innovation to meet segment needs, ensuring relevance and maximizing sales potential.</li>
</ul>
<h4 id="heading-customized-loyalty-programs">Customized Loyalty Programs</h4>
<p>Loyalty programs can enhance customer retention and lifetime value, but the incentives must be tailored to resonate with each segment's priorities.</p>
<ul>
<li><strong>Consumer Segment:</strong> Offer points-based rewards, exclusive access, personalized offers, and birthday rewards to appeal to their desire for value and recognition.</li>
<li><strong>Corporate Clients:</strong> Implement tiered programs with volume discounts, account management, priority support, and customized solutions to cater to their focus on cost-effectiveness and efficiency.</li>
<li><strong>Home Office Professionals:</strong> Provide subscription-based programs with personalized discounts, early access to new products, exclusive content, and priority support to cater to their need for convenience and specialized solutions.</li>
</ul>
<h4 id="heading-dynamic-pricing-strategies">Dynamic Pricing Strategies</h4>
<p>Dynamic pricing can optimize profitability by aligning prices with each segment's perceived value and purchasing power.</p>
<ul>
<li><strong>Action:</strong> Implement algorithms considering demand, seasonality, competitor pricing, and customer behavior.</li>
<li><strong>Outcome:</strong> Optimized pricing for each segment, maximizing profitability and sales conversions while remaining competitive.</li>
</ul>
<h4 id="heading-predictive-analytics-for-proactive-decision-making">Predictive Analytics for Proactive Decision-Making</h4>
<p>Predictive analytics enables data-driven decision-making, allowing for proactive inventory management, targeted marketing campaigns, and personalized customer experiences.</p>
<ul>
<li><strong>Action:</strong> Leverage analytics to forecast buying behavior, identify trends, and personalize offers.</li>
<li><strong>Outcome:</strong> Proactive inventory management to avoid stockouts and overstocking, targeted marketing campaigns that resonate with each segment's unique preferences, and enhanced customer experience through personalized recommendations and offers.</li>
</ul>
<p>The SuperStore dataset analysis unequivocally demonstrates the criticality of customer segmentation for strategic planning and execution. It provides a comprehensive framework to leverage customer insights for optimized business outcomes.</p>
<p>A data-driven approach acknowledging the unique characteristics and preferences of each customer segment is paramount to sustainable growth. This involves tailoring marketing campaigns, product offerings, loyalty programs, and pricing strategies.</p>
<p>By understanding customer behavior and preferences, your organization can:</p>
<ul>
<li><strong>Enhance Engagement:</strong> Develop targeted campaigns addressing specific pain points and aspirations.</li>
<li><strong>Improve Satisfaction:</strong> Provide personalized experiences and offerings catering to unique needs.</li>
<li><strong>Drive Revenue:</strong> Optimize pricing, product mix, and promotions based on purchasing power and behavior.</li>
</ul>
<p>Integrating data-driven insights into strategic initiatives enables informed decision-making, resource optimization, and competitive advantage. </p>
<h3 id="heading-customer-loyalty-1">Customer Loyalty</h3>
<p>The following analysis seeks to pinpoint the key customer segments within our dataset that significantly influence business outcomes. Our goal is to unearth the characteristics and behaviors of high-value customers, enabling targeted strategies to enhance retention, loyalty, and ultimately drive growth. </p>
<p>By delving into purchasing patterns, demographics, and engagement metrics, we will uncover hidden opportunities and prioritize actions that maximize customer lifetime value. </p>
<p>Below you can see the code we'll run and the output it generates:</p>
<pre><code class="lang-python"><span class="hljs-comment"># Group the data by Customer ID, Customer Name, Segments, and calculate the frequency of orders for each customer</span>
customer_order_frequency = df.groupby([<span class="hljs-string">'Customer ID'</span>, <span class="hljs-string">'Customer Name'</span>, <span class="hljs-string">'Segment'</span>])[<span class="hljs-string">'Order ID'</span>].count().reset_index()

<span class="hljs-comment"># Rename the column to represent the frequency of orders</span>
customer_order_frequency.rename(columns={<span class="hljs-string">'Order ID'</span>: <span class="hljs-string">'Total Orders'</span>}, inplace=<span class="hljs-literal">True</span>)

<span class="hljs-comment"># Identify repeat customers (customers with order frequency greater than 1)</span>
repeat_customers = customer_order_frequency[customer_order_frequency[<span class="hljs-string">'Total Orders'</span>] &gt;= <span class="hljs-number">1</span>]

<span class="hljs-comment"># Sort "repeat_customers" in descending order based on the "Order Frequency" column</span>
repeat_customers_sorted = repeat_customers.sort_values(by=<span class="hljs-string">'Total Orders'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Print the result- the first 10 and reset index</span>
print(repeat_customers_sorted.head(<span class="hljs-number">12</span>).reset_index(drop=<span class="hljs-literal">True</span>))
</code></pre>
<pre><code class="lang-python">Customer ID        Customer Name      Segment  Total Orders
<span class="hljs-number">0</span>     WB<span class="hljs-number">-21850</span>        William Brown     Consumer            <span class="hljs-number">35</span>
<span class="hljs-number">1</span>     PP<span class="hljs-number">-18955</span>           Paul Prost  Home Office            <span class="hljs-number">34</span>
<span class="hljs-number">2</span>     MA<span class="hljs-number">-17560</span>         Matt Abelman  Home Office            <span class="hljs-number">34</span>
<span class="hljs-number">3</span>     JL<span class="hljs-number">-15835</span>             John Lee     Consumer            <span class="hljs-number">33</span>
<span class="hljs-number">4</span>     CK<span class="hljs-number">-12205</span>  Chloris Kastensmidt     Consumer            <span class="hljs-number">32</span>
<span class="hljs-number">5</span>     SV<span class="hljs-number">-20365</span>          Seth Vernon     Consumer            <span class="hljs-number">32</span>
<span class="hljs-number">6</span>     JD<span class="hljs-number">-15895</span>     Jonathan Doherty    Corporate            <span class="hljs-number">32</span>
<span class="hljs-number">7</span>     AP<span class="hljs-number">-10915</span>       Arthur Prichep     Consumer            <span class="hljs-number">31</span>
<span class="hljs-number">8</span>     ZC<span class="hljs-number">-21910</span>     Zuschuss Carroll     Consumer            <span class="hljs-number">31</span>
<span class="hljs-number">9</span>     EP<span class="hljs-number">-13915</span>           Emily Phan     Consumer            <span class="hljs-number">31</span>
<span class="hljs-number">10</span>    LC<span class="hljs-number">-16870</span>        Lena Cacioppo     Consumer            <span class="hljs-number">30</span>
<span class="hljs-number">11</span>    Dp<span class="hljs-number">-13240</span>          Dean percer  Home Office            <span class="hljs-number">29</span>
</code></pre>
<pre><code class="lang-python"><span class="hljs-comment"># Group the data by customer IDs and calculate the total purchase (sales) for each customer</span>
customer_sales = df.groupby([<span class="hljs-string">'Customer ID'</span>, <span class="hljs-string">'Customer Name'</span>, <span class="hljs-string">'Segment'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

<span class="hljs-comment"># Sort the customers based on their total purchase in descending order to identify top spenders</span>
top_spenders = customer_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Print the top-spending customers</span>
print(top_spenders.head(<span class="hljs-number">10</span>).reset_index(drop=<span class="hljs-literal">True</span>)) 

Customer ID       Customer Name      Segment      Sales
<span class="hljs-number">0</span>    SM<span class="hljs-number">-20320</span>         Sean Miller  Home Office  <span class="hljs-number">25043.050</span>
<span class="hljs-number">1</span>    TC<span class="hljs-number">-20980</span>        Tamara Chand    Corporate  <span class="hljs-number">19052.218</span>
<span class="hljs-number">2</span>    RB<span class="hljs-number">-19360</span>        Raymond Buch     Consumer  <span class="hljs-number">15117.339</span>
<span class="hljs-number">3</span>    TA<span class="hljs-number">-21385</span>        Tom Ashbrook  Home Office  <span class="hljs-number">14595.620</span>
<span class="hljs-number">4</span>    AB<span class="hljs-number">-10105</span>       Adrian Barton     Consumer  <span class="hljs-number">14473.571</span>
<span class="hljs-number">5</span>    KL<span class="hljs-number">-16645</span>        Ken Lonsdale     Consumer  <span class="hljs-number">14175.229</span>
<span class="hljs-number">6</span>    SC<span class="hljs-number">-20095</span>        Sanjit Chand     Consumer  <span class="hljs-number">14142.334</span>
<span class="hljs-number">7</span>    HL<span class="hljs-number">-15040</span>        Hunter Lopez     Consumer  <span class="hljs-number">12873.298</span>
<span class="hljs-number">8</span>    SE<span class="hljs-number">-20110</span>        Sanjit Engle     Consumer  <span class="hljs-number">12209.438</span>
<span class="hljs-number">9</span>    CC<span class="hljs-number">-12370</span>  Christopher Conant     Consumer  <span class="hljs-number">12129.07</span>
</code></pre>
<h4 id="heading-understanding-repeat-purchase-behaviors">Understanding Repeat Purchase Behaviors</h4>
<p>The repeat purchase behavior of our customers reveals who is coming back and how often. Our analysis shows that certain customers make frequent purchases, highlighting their loyalty and the effectiveness of our engagement strategies. </p>
<p>For example, William Brown, a consumer, tops the list with 35 orders, indicating high engagement with our offerings.</p>
<h4 id="heading-action-points">Action Points:</h4>
<ul>
<li><strong>Personalize Communication</strong>: Tailor marketing messages and promotions to the needs and preferences of frequent buyers to maintain their interest and encourage continued patronage.</li>
<li><strong>Reward Loyalty</strong>: Implement a loyalty program that rewards repeat purchases, thereby increasing customer retention rates.</li>
<li><strong>Feedback Collection</strong>: Regularly gather feedback from repeat customers to refine product offerings and service delivery.</li>
</ul>
<h4 id="heading-identifying-and-nurturing-top-spenders">Identifying and Nurturing Top Spenders</h4>
<p>Assessing who spends the most within our customer segments provides a clear direction for resource allocation in marketing and customer service efforts. </p>
<p>Sean Miller, from the Home Office segment, has the highest expenditure with over $25,000 spent. This information is crucial for developing targeted strategies that cater to high-value customers.</p>
<h4 id="heading-strategic-recommendations">Strategic Recommendations:</h4>
<ul>
<li><strong>Enhanced Customer Support</strong>: Offer dedicated support and exclusive services to top spenders to enhance their buying experience.</li>
<li><strong>Custom Offers</strong>: Create special offers that cater to the unique needs and preferences of the highest spenders to increase their purchase frequency.</li>
<li><strong>Strategic Upselling</strong>: Use data-driven insights to identify upselling opportunities tailored to the interests of top spenders.</li>
</ul>
<h4 id="heading-utilizing-data-for-targeted-marketing">Utilizing Data for Targeted Marketing</h4>
<p>The detailed breakdown of customer spending and order frequency allows us to segment our marketing efforts more effectively. </p>
<p>For instance, knowing that home office customers like Sean Miller and Tom Ashbrook are among the top spenders suggests a high potential for targeted marketing campaigns designed to cater to home office setups.</p>
<h4 id="heading-implementable-actions">Implementable Actions:</h4>
<ul>
<li><strong>Segment-Specific Campaigns</strong>: Design marketing campaigns that address the specific needs of different segments, such as corporate and home office, enhancing relevance and effectiveness.</li>
<li><strong>Data-Driven Product Recommendations</strong>: Leverage data on past purchases to recommend relevant products that meet the evolving needs of our customers.</li>
<li><strong>Incentivize Higher Spend</strong>: Introduce tiered pricing strategies that incentivize higher spend, particularly within segments that show a propensity for larger transactions.</li>
</ul>
<h4 id="heading-empowering-strategic-decisions-through-customer-segmentation">Empowering Strategic Decisions Through Customer Segmentation</h4>
<p>Our customer segmentation analysis provides a foundation for making informed, strategic decisions that enhance customer satisfaction and loyalty. By understanding and acting on the behaviors of our customers—identifying who are our most frequent shoppers and top spenders—we can tailor our efforts to maximize impact. </p>
<p>This approach not only boosts customer loyalty but also drives increased revenue, ensuring our competitive edge in the market.</p>
<h3 id="heading-popular-mode-of-shipment">Popular Mode of Shipment</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-20.png" alt="Image" width="600" height="400" loading="lazy">
<em>Popular Mode of Shipment</em></p>
<h4 id="heading-analyzing-shipping-preferences">Analyzing Shipping Preferences</h4>
<p>Our dataset reveals the distribution of shipping preferences among our customers, which is crucial for optimizing logistics and enhancing customer satisfaction. </p>
<p>The "Popular Mode Of Shipment" pie chart indicates that Standard Class shipping is overwhelmingly preferred, accounting for 59.8% of shipments. This is followed by Second Class at 19.4%, First Class at 15.3%, and Same Day at 5.5%.</p>
<h4 id="heading-strategic-implications">Strategic Implications</h4>
<p>The dominance of Standard Class shipping underscores its importance as a reliable and cost-effective option for the majority of our customers. However, the presence of faster options like First Class and Same Day shipping highlights a segment of the market with different priorities—speed and convenience.</p>
<p>This data can drive growth and optimization in several ways:</p>
<p><strong>Tailored Shipping Options:</strong></p>
<ul>
<li><strong>Consumers:</strong> Offer a tiered shipping program where Standard Class is the default, but members of the loyalty program receive free shipping on orders over a certain threshold. This incentivizes higher-value purchases while catering to their preference for cost-effectiveness.</li>
<li><strong>Corporate Clients:</strong> Introduce a "Corporate Shipping Program" with negotiated rates for bulk orders and expedited shipping options. This could include dedicated account managers for seamless logistics coordination and personalized shipping solutions.</li>
<li><strong>Home Office Professionals:</strong> Offer a subscription-based service with free or discounted expedited shipping for a flat monthly fee. This caters to their desire for convenience and reliable delivery.</li>
</ul>
<p><strong>Dynamic Pricing:</strong></p>
<ul>
<li><strong>Peak Season Surcharges:</strong> During peak shopping periods, implement surcharges for expedited shipping to manage demand and allocate resources efficiently.</li>
<li><strong>Regional Pricing:</strong> Adjust shipping prices based on the customer's location to account for varying shipping costs and ensure fair pricing.</li>
<li><strong>Promotional Discounts:</strong> Offer limited-time discounts on specific shipping methods to stimulate sales and entice customers to try faster options.</li>
</ul>
<p><strong>Partnership Opportunities:</strong></p>
<ul>
<li><strong>Negotiated Rates:</strong> Partner with multiple carriers to secure competitive rates for various shipping methods, ensuring cost-effective options for both SuperStore and its customers.</li>
<li><strong>Hybrid Shipping:</strong> Explore partnerships with local delivery services to offer same-day or next-day delivery in select areas, catering to customers who prioritize speed.</li>
<li><strong>International Expansion:</strong> Partner with international shipping providers to expand SuperStore's reach and offer global shipping options.</li>
</ul>
<p><strong>Operational Efficiency:</strong></p>
<ul>
<li><strong>Warehouse Optimization:</strong> Analyze shipping data to identify popular products and strategically locate them within the warehouse for faster order fulfillment.</li>
<li><strong>Route Optimization:</strong> Utilize route planning software to optimize delivery routes and reduce transportation costs.</li>
<li><strong>Packaging Efficiency:</strong> Analyze product dimensions and packaging materials to minimize shipping costs and reduce waste.</li>
</ul>
<p><strong>Customer Communication:</strong></p>
<ul>
<li><strong>Real-Time Tracking:</strong> Integrate shipping tracking tools into the website and customer communication channels to provide real-time updates on order status and estimated delivery times.</li>
<li><strong>Proactive Notifications:</strong> Send automated notifications about shipping delays or changes in delivery schedules to manage customer expectations and reduce inquiries.</li>
<li><strong>Personalized Recommendations:</strong> Based on past purchase history and shipping preferences, recommend suitable shipping options during checkout to enhance the customer experience.</li>
</ul>
<p><strong>Feedback Loop:</strong></p>
<ul>
<li><strong>Post-Purchase Surveys:</strong> Collect feedback on shipping experiences through post-purchase surveys or email campaigns to identify areas for improvement.</li>
<li><strong>Online Reviews and Social Media:</strong> Monitor online reviews and social media mentions related to shipping to address concerns and maintain a positive brand image.</li>
<li><strong>Continuous Improvement:</strong> Regularly analyze feedback data to identify trends and implement changes to enhance shipping services.</li>
</ul>
<h3 id="heading-geographical-analysis">Geographical Analysis</h3>
<p>A comprehensive geographic analysis reveals a wealth of opportunities for SuperStore to optimize its market penetration and sales strategy across various states and cities. This granular assessment provides actionable insights that will empower the company to concentrate its efforts on high-yield regions, tailor product offerings to local preferences, and unlock hidden pockets of profitability. </p>
<p>Below is the code that we will run and the output it produces: </p>
<pre><code class="lang-python"><span class="hljs-comment"># Customers per state</span>

state = df[<span class="hljs-string">'State'</span>].value_counts().reset_index()
state = state.rename(columns={<span class="hljs-string">'index'</span>:<span class="hljs-string">'State'</span>, <span class="hljs-string">'State'</span>:<span class="hljs-string">'Number_of_customers'</span>})

print(state.head(<span class="hljs-number">20</span>))

<span class="hljs-comment"># Customers per city</span>

city = df[<span class="hljs-string">'City'</span>].value_counts().reset_index()
city= city.rename(columns={<span class="hljs-string">'index'</span>:<span class="hljs-string">'City'</span>, <span class="hljs-string">'City'</span>:<span class="hljs-string">'Number_of_customers'</span>})

print(city.head(<span class="hljs-number">15</span>))

<span class="hljs-comment"># Sales per state</span>

<span class="hljs-comment"># Group the data by state and calculate the total purchases (sales) for each state</span>
state_sales = df.groupby([<span class="hljs-string">'State'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

<span class="hljs-comment"># Sort the states based on their total sales in descending order to identify top spenders</span>
top_sales = state_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Print the states</span>
print(top_sales.head(<span class="hljs-number">20</span>).reset_index(drop=<span class="hljs-literal">True</span>))

<span class="hljs-comment"># Group the data by state and calculate the total purchase (sales) for each city</span>
city_sales = df.groupby([<span class="hljs-string">'City'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

<span class="hljs-comment"># Sort the cities based on their sales in descending order to identify top cities</span>
top_city_sales = city_sales.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=<span class="hljs-literal">False</span>)

<span class="hljs-comment"># Print the states</span>
print(top_city_sales.head(<span class="hljs-number">20</span>).reset_index(drop=<span class="hljs-literal">True</span>))

state_city_sales = df.groupby([<span class="hljs-string">'State'</span>,<span class="hljs-string">'City'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

print(state_city_sales.head(<span class="hljs-number">20</span>))
</code></pre>
<pre><code class="lang-python"> Number_of_customers  count
<span class="hljs-number">0</span>           California   <span class="hljs-number">1946</span>
<span class="hljs-number">1</span>             New York   <span class="hljs-number">1097</span>
<span class="hljs-number">2</span>                Texas    <span class="hljs-number">973</span>
<span class="hljs-number">3</span>         Pennsylvania    <span class="hljs-number">582</span>
<span class="hljs-number">4</span>           Washington    <span class="hljs-number">504</span>
<span class="hljs-number">5</span>             Illinois    <span class="hljs-number">483</span>
<span class="hljs-number">6</span>                 Ohio    <span class="hljs-number">454</span>
<span class="hljs-number">7</span>              Florida    <span class="hljs-number">373</span>
<span class="hljs-number">8</span>             Michigan    <span class="hljs-number">253</span>
<span class="hljs-number">9</span>       North Carolina    <span class="hljs-number">247</span>
<span class="hljs-number">10</span>            Virginia    <span class="hljs-number">224</span>
<span class="hljs-number">11</span>             Arizona    <span class="hljs-number">223</span>
<span class="hljs-number">12</span>           Tennessee    <span class="hljs-number">183</span>
<span class="hljs-number">13</span>            Colorado    <span class="hljs-number">179</span>
<span class="hljs-number">14</span>             Georgia    <span class="hljs-number">177</span>
<span class="hljs-number">15</span>            Kentucky    <span class="hljs-number">137</span>
<span class="hljs-number">16</span>             Indiana    <span class="hljs-number">135</span>
<span class="hljs-number">17</span>       Massachusetts    <span class="hljs-number">135</span>
<span class="hljs-number">18</span>              Oregon    <span class="hljs-number">122</span>
<span class="hljs-number">19</span>          New Jersey    <span class="hljs-number">122</span>

 Number_of_customers  count
<span class="hljs-number">0</span>        New York City    <span class="hljs-number">891</span>
<span class="hljs-number">1</span>          Los Angeles    <span class="hljs-number">728</span>
<span class="hljs-number">2</span>         Philadelphia    <span class="hljs-number">532</span>
<span class="hljs-number">3</span>        San Francisco    <span class="hljs-number">500</span>
<span class="hljs-number">4</span>              Seattle    <span class="hljs-number">426</span>
<span class="hljs-number">5</span>              Houston    <span class="hljs-number">374</span>
<span class="hljs-number">6</span>              Chicago    <span class="hljs-number">308</span>
<span class="hljs-number">7</span>             Columbus    <span class="hljs-number">221</span>
<span class="hljs-number">8</span>            San Diego    <span class="hljs-number">170</span>
<span class="hljs-number">9</span>          Springfield    <span class="hljs-number">161</span>
<span class="hljs-number">10</span>              Dallas    <span class="hljs-number">156</span>
<span class="hljs-number">11</span>        Jacksonville    <span class="hljs-number">125</span>
<span class="hljs-number">12</span>             Detroit    <span class="hljs-number">115</span>
<span class="hljs-number">13</span>              Newark     <span class="hljs-number">92</span>
<span class="hljs-number">14</span>             Jackson     <span class="hljs-number">82</span>

       State        Sales
<span class="hljs-number">0</span>       California  <span class="hljs-number">446306.4635</span>
<span class="hljs-number">1</span>         New York  <span class="hljs-number">306361.1470</span>
<span class="hljs-number">2</span>            Texas  <span class="hljs-number">168572.5322</span>
<span class="hljs-number">3</span>       Washington  <span class="hljs-number">135206.8500</span>
<span class="hljs-number">4</span>     Pennsylvania  <span class="hljs-number">116276.6500</span>
<span class="hljs-number">5</span>          Florida   <span class="hljs-number">88436.5320</span>
<span class="hljs-number">6</span>         Illinois   <span class="hljs-number">79236.5170</span>
<span class="hljs-number">7</span>         Michigan   <span class="hljs-number">76136.0740</span>
<span class="hljs-number">8</span>             Ohio   <span class="hljs-number">75130.3500</span>
<span class="hljs-number">9</span>         Virginia   <span class="hljs-number">70636.7200</span>
<span class="hljs-number">10</span>  North Carolina   <span class="hljs-number">55165.9640</span>
<span class="hljs-number">11</span>         Indiana   <span class="hljs-number">48718.4000</span>
<span class="hljs-number">12</span>         Georgia   <span class="hljs-number">48219.1100</span>
<span class="hljs-number">13</span>        Kentucky   <span class="hljs-number">36458.3900</span>
<span class="hljs-number">14</span>         Arizona   <span class="hljs-number">35272.6570</span>
<span class="hljs-number">15</span>      New Jersey   <span class="hljs-number">34610.9720</span>
<span class="hljs-number">16</span>        Colorado   <span class="hljs-number">31841.5980</span>
<span class="hljs-number">17</span>       Wisconsin   <span class="hljs-number">31173.4300</span>
<span class="hljs-number">18</span>       Tennessee   <span class="hljs-number">30661.8730</span>
<span class="hljs-number">19</span>       Minnesota   <span class="hljs-number">29863.1500</span>

 City        Sales
<span class="hljs-number">0</span>   New York City  <span class="hljs-number">252462.5470</span>
<span class="hljs-number">1</span>     Los Angeles  <span class="hljs-number">173420.1810</span>
<span class="hljs-number">2</span>         Seattle  <span class="hljs-number">116106.3220</span>
<span class="hljs-number">3</span>   San Francisco  <span class="hljs-number">109041.1200</span>
<span class="hljs-number">4</span>    Philadelphia  <span class="hljs-number">108841.7490</span>
<span class="hljs-number">5</span>         Houston   <span class="hljs-number">63956.1428</span>
<span class="hljs-number">6</span>         Chicago   <span class="hljs-number">47820.1330</span>
<span class="hljs-number">7</span>       San Diego   <span class="hljs-number">47521.0290</span>
<span class="hljs-number">8</span>    Jacksonville   <span class="hljs-number">44713.1830</span>
<span class="hljs-number">9</span>         Detroit   <span class="hljs-number">42446.9440</span>
<span class="hljs-number">10</span>    Springfield   <span class="hljs-number">41827.8100</span>
<span class="hljs-number">11</span>       Columbus   <span class="hljs-number">38662.5630</span>
<span class="hljs-number">12</span>         Newark   <span class="hljs-number">28448.0490</span>
<span class="hljs-number">13</span>       Columbia   <span class="hljs-number">25283.3240</span>
<span class="hljs-number">14</span>        Jackson   <span class="hljs-number">24963.8580</span>
<span class="hljs-number">15</span>      Lafayette   <span class="hljs-number">24944.2800</span>
<span class="hljs-number">16</span>    San Antonio   <span class="hljs-number">21843.5280</span>
<span class="hljs-number">17</span>     Burlington   <span class="hljs-number">21668.0820</span>
<span class="hljs-number">18</span>      Arlington   <span class="hljs-number">20214.5320</span>
<span class="hljs-number">19</span>         Dallas   <span class="hljs-number">20127.9482</span>

  State           City      Sales
<span class="hljs-number">0</span>   Alabama         Auburn   <span class="hljs-number">1766.830</span>
<span class="hljs-number">1</span>   Alabama        Decatur   <span class="hljs-number">3374.820</span>
<span class="hljs-number">2</span>   Alabama       Florence   <span class="hljs-number">1997.350</span>
<span class="hljs-number">3</span>   Alabama         Hoover    <span class="hljs-number">525.850</span>
<span class="hljs-number">4</span>   Alabama     Huntsville   <span class="hljs-number">2484.370</span>
<span class="hljs-number">5</span>   Alabama         Mobile   <span class="hljs-number">5462.990</span>
<span class="hljs-number">6</span>   Alabama     Montgomery   <span class="hljs-number">3722.730</span>
<span class="hljs-number">7</span>   Alabama     Tuscaloosa    <span class="hljs-number">175.700</span>
<span class="hljs-number">8</span>   Arizona       Avondale    <span class="hljs-number">946.808</span>
<span class="hljs-number">9</span>   Arizona  Bullhead City     <span class="hljs-number">22.288</span>
<span class="hljs-number">10</span>  Arizona       Chandler   <span class="hljs-number">1067.403</span>
<span class="hljs-number">11</span>  Arizona        Gilbert   <span class="hljs-number">4172.382</span>
<span class="hljs-number">12</span>  Arizona       Glendale   <span class="hljs-number">2917.865</span>
<span class="hljs-number">13</span>  Arizona           Mesa   <span class="hljs-number">4037.740</span>
<span class="hljs-number">14</span>  Arizona         Peoria   <span class="hljs-number">1341.352</span>
<span class="hljs-number">15</span>  Arizona        Phoenix  <span class="hljs-number">11000.257</span>
<span class="hljs-number">16</span>  Arizona     Scottsdale   <span class="hljs-number">1466.307</span>
<span class="hljs-number">17</span>  Arizona   Sierra Vista     <span class="hljs-number">76.072</span>
<span class="hljs-number">18</span>  Arizona          Tempe   <span class="hljs-number">1070.302</span>
<span class="hljs-number">19</span>  Arizona         Tucson   <span class="hljs-number">6313.016</span>
</code></pre>
<p>Now let's dig into this data a bit more:</p>
<h4 id="heading-state-level-analysis-beyond-the-obvious">State-Level Analysis: Beyond the Obvious</h4>
<p>While California boasts the largest customer base, the data reveals a nuanced landscape where success isn't solely determined by sheer numbers. </p>
<p>New York's higher sales per customer, despite a smaller customer base, suggest a lucrative market with a preference for premium products or larger order quantities. </p>
<p>Texas, while ranking third in customer count, emerges as a burgeoning market with significant untapped potential due to its large population and thriving economy. </p>
<p>Washington and Pennsylvania, though smaller in customer base, exhibit robust sales figures, hinting at untapped potential that could be unlocked through targeted marketing and increased brand visibility.</p>
<p><strong>Strategic Recommendations:</strong></p>
<ul>
<li><strong>High-Growth Regions:</strong> Prioritize Texas, Washington, and Pennsylvania for expansion. Consider allocating additional resources to marketing campaigns, expanding distribution networks, and tailoring product offerings to local preferences.</li>
<li><strong>High-Value Markets:</strong> New York presents an opportunity to cultivate a loyal customer base with a penchant for premium products. Consider introducing exclusive product lines, loyalty programs with high-value rewards, and personalized shopping experiences.</li>
<li><strong>Maximizing Market Share:</strong> In California, focus on increasing customer engagement and average order value through targeted promotions, personalized recommendations, and data-driven upselling strategies.</li>
</ul>
<h4 id="heading-city-level-analysis-pinpointing-urban-opportunities">City-Level Analysis: Pinpointing Urban Opportunities</h4>
<p>Drilling down to the city level reveals even more granular insights into customer behavior and preferences. </p>
<p>While New York City leads in both customer count and total sales, cities like Los Angeles and Seattle demonstrate impressive sales figures despite smaller customer bases, indicating a high-value segment with a willingness to spend. </p>
<p>Surprisingly, metropolitan areas like Houston and Chicago, with their sizeable populations, present significant untapped potential due to underperforming sales figures.</p>
<p><strong>Strategic Recommendations:</strong></p>
<ul>
<li><strong>Targeted Urban Campaigns:</strong> Launch hyper-targeted campaigns in Houston and Chicago, emphasizing brand awareness, local partnerships, and product assortments tailored to the unique preferences of each city.</li>
<li><strong>Market Expansion:</strong> Capitalize on the affluent customer base in Seattle and Los Angeles by introducing premium product lines, expanding service offerings, and hosting exclusive events to foster loyalty and drive repeat business.</li>
<li><strong>Loyalty Enhancement:</strong> Focus on retention strategies in New York City, such as personalized loyalty programs, exclusive events, and concierge services, to maintain and strengthen relationships with high-value customers.</li>
</ul>
<h4 id="heading-granular-insights-hidden-gems-within-states">Granular Insights: Hidden Gems Within States</h4>
<p>A more detailed analysis reveals hidden pockets of profitability within individual states. For instance, Arizona boasts cities like Phoenix and Tucson that significantly contribute to overall sales, highlighting the importance of understanding local dynamics within each state.</p>
<p><strong>Strategic Recommendations:</strong></p>
<ul>
<li><strong>Hyperlocal Marketing:</strong> Tailor marketing campaigns to specific cities within each state, leveraging local insights, cultural nuances, and community partnerships to maximize engagement and drive conversions.</li>
<li><strong>Localized Product Assortment:</strong> Optimize product offerings in each city based on local demand and preferences, ensuring the most relevant and appealing products are readily available.</li>
<li><strong>Data-Driven Expansion:</strong> Utilize data analytics to identify untapped markets within high-potential states, enabling strategic expansion into specific cities where the brand can resonate with local audiences.</li>
</ul>
<p>By adopting a granular, data-driven approach to geographic analysis, SuperStore can unlock new avenues for growth, optimize its market penetration, and achieve sustained profitability across diverse regions. </p>
<p>The key lies in understanding the unique characteristics and preferences of each market and tailoring strategies accordingly. This will not only drive sales but also foster strong customer relationships and brand loyalty, positioning SuperStore as a market leader that truly understands and caters to the needs of its diverse customer base.</p>
<h3 id="heading-product-category-analysis">Product Category Analysis</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-21.png" alt="Image" width="600" height="400" loading="lazy">
<em>Top Product Categories Based on Sales</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-22.png" alt="Image" width="600" height="400" loading="lazy">
<em>Top Product Categories Based on Sales</em></p>
<p>Now we'll discover which products are truly driving revenue, where your profit margins shine, and which categories are ripe for strategic investment. </p>
<p>Below is the code that we will run and the output it produces: </p>
<pre><code>
## Product Analysis

### Product Category Analysis

- Investigate the sales performance <span class="hljs-keyword">of</span> different product

# Types <span class="hljs-keyword">of</span> products <span class="hljs-keyword">in</span> the Stores

products = df[<span class="hljs-string">'Category'</span>].unique()
print(products)

product_subcategory = df[<span class="hljs-string">'Sub-Category'</span>].unique()
print(product_subcategory)

# Types <span class="hljs-keyword">of</span> sub category

product_subcategory = df[<span class="hljs-string">'Sub-Category'</span>].nunique()
print(product_subcategory)

# Group the data by product category and how many sub-category it has
subcategory_count = df.groupby(<span class="hljs-string">'Category'</span>)[<span class="hljs-string">'Sub-Category'</span>].nunique().reset_index()
# sort by ascending order
subcategory_count = subcategory_count.sort_values(by=<span class="hljs-string">'Sub-Category'</span>, ascending=False)
# Print the states
print(subcategory_count)

subcategory_count_sales = df.groupby([<span class="hljs-string">'Category'</span>,<span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

print(subcategory_count_sales)

# Group the data by product category versus the sales <span class="hljs-keyword">from</span> each product category
product_category = df.groupby([<span class="hljs-string">'Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

# Sort the product category <span class="hljs-keyword">in</span> their descending order and identify top product category
top_product_category = product_category.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=False)

# Print the states
print(top_product_category.reset_index(drop=True))

# Plotting a pie chart
plt.pie(top_product_category[<span class="hljs-string">'Sales'</span>], labels=top_product_category[<span class="hljs-string">'Category'</span>], autopct=<span class="hljs-string">'%1.1f%%'</span>)

# set the labels <span class="hljs-keyword">of</span> the pie chart
plt.title(<span class="hljs-string">'Top Product Categories Based on Sales'</span>)

plt.show()


# Group the data by product sub category versus the sales
product_subcategory = df.groupby([<span class="hljs-string">'Sub-Category'</span>])[<span class="hljs-string">'Sales'</span>].sum().reset_index()

# Sort the product category <span class="hljs-keyword">in</span> their descending order and identify top product category
top_product_subcategory = product_subcategory.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=False)

# Print the states
print(top_product_subcategory.reset_index(drop=True))


top_product_subcategory = top_product_subcategory.sort_values(by=<span class="hljs-string">'Sales'</span>, ascending=True)

# Ploting a bar graph

plt.barh(top_product_subcategory[<span class="hljs-string">'Sub-Category'</span>], top_product_subcategory[<span class="hljs-string">'Sales'</span>])

# Labels
plt.title(<span class="hljs-string">'Top Product Categories Based on Sales'</span>)
plt.xlabel(<span class="hljs-string">'Product Sub-Category'</span>)
plt.ylabel(<span class="hljs-string">'Total Sales'</span>)
plt.xticks(rotation=<span class="hljs-number">0</span>)

plt.show()
</code></pre><h4 id="heading-sales-distribution-a-balanced-portfolio-with-a-technological-tilt">Sales Distribution: A Balanced Portfolio with a Technological Tilt</h4>
<p>The product portfolio demonstrates a balanced distribution across three primary categories: Technology (36.6%), Furniture (32.2%), and Office Supplies (31.2%). This near-equal distribution signifies a diverse customer base with varied needs. </p>
<p>However, the slight dominance of technology products indicates a potential growth trajectory in this sector, aligning with current market trends and consumer preferences.</p>
<h4 id="heading-sub-category-spotlight-identifying-stars-and-hidden-gems">Sub-Category Spotlight: Identifying Stars and Hidden Gems</h4>
<p>Drilling down into sub-categories unveils a more nuanced picture:</p>
<ul>
<li><strong>Star Performers:</strong> Phones and Chairs emerge as the undeniable champions, boasting the highest gross sales. This signals a robust market demand and potentially healthy profit margins, warranting a strategic focus on inventory management, marketing initiatives, and supplier relationships.</li>
<li><strong>Mid-Tier Contenders:</strong> Storage, Tables, and Accessories exhibit substantial sales, although not reaching the top echelons. These categories present opportunities for targeted promotions, bundled offers, and cross-selling strategies to elevate their performance and capture a larger market share.</li>
<li><strong>Dormant Potential:</strong> Fasteners, Labels, and Envelopes linger at the lower end of the spectrum, representing a smaller share of sales. While these items may be perceived as ancillary, they offer potential for growth through aggressive marketing, creative bundling with higher-demand products, or strategic re-evaluation of their role in the product mix.</li>
</ul>
<h4 id="heading-strategic-roadmap-from-insights-to-actionable-strategies">Strategic Roadmap: From Insights to Actionable Strategies</h4>
<ul>
<li><strong>High-Value Focus:</strong> Prioritize inventory allocation and marketing resources for top-performing sub-categories like Phones and Chairs. Explore strategic partnerships with suppliers to secure volume discounts and ensure consistent stock availability.</li>
<li><strong>Mid-Tier Boost:</strong> Implement targeted promotions, cross-selling strategies, and bundled offers for Storage, Tables, and Accessories to stimulate demand and increase average order value.</li>
<li><strong>Dormant Potential Activation:</strong> Conduct comprehensive market research to understand the factors influencing low demand for Fasteners, Labels, and Envelopes. Consider adjusting pricing strategies, featuring these products more prominently in marketing materials, or utilizing them as promotional items to drive traffic and increase basket size.</li>
</ul>
<h4 id="heading-leveraging-data-for-precision-marketing-and-continuous-improvement">Leveraging Data for Precision Marketing and Continuous Improvement</h4>
<ul>
<li><strong>Targeted Campaigns:</strong> Utilize customer purchase data to segment customers effectively and create personalized marketing campaigns that resonate with their specific needs and preferences.</li>
<li><strong>Dynamic Pricing:</strong> Implement dynamic pricing models for high-demand items like Phones, leveraging fluctuations in demand to maximize profitability without alienating customers.</li>
<li><strong>Feedback Loop:</strong> Establish a robust mechanism for gathering and analyzing customer feedback, particularly for top-selling and underperforming products. This iterative process allows for continuous improvement and ensures product offerings remain aligned with evolving customer expectations.</li>
</ul>
<p>This comprehensive product category analysis serves as a compass, guiding SuperStore towards a more refined and profitable product strategy. By embracing data-driven insights and implementing targeted actions, the company can capitalize on high-growth opportunities, optimize inventory management, and foster a deeper understanding of customer preferences. </p>
<p>This strategic approach will not only maximize short-term revenue but also cultivate long-term customer loyalty and sustained growth in an ever-evolving market.</p>
<h3 id="heading-sales-analysis">Sales Analysis</h3>
<p>Analyzing our sales data over several years provides a clear trajectory of growth and helps us understand seasonal fluctuations that affect our business. This analysis is essential for strategic planning, resource allocation, and performance forecasting. </p>
<h4 id="heading-yearly-sales-analysis-2014-2018-capitalizing-on-growth-and-navigating-fluctuations">Yearly Sales Analysis (2014-2018): Capitalizing on Growth and Navigating Fluctuations</h4>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-24.png" alt="Image" width="600" height="400" loading="lazy">
<em>Yearly Sales from 2014 to 2019</em></p>
<p>The consistent sales growth from 2014 to 2018, with a temporary dip in 2016, presents a valuable opportunity for strategic refinement and growth acceleration.</p>
<p><strong>Actionable Insights:</strong></p>
<ul>
<li><strong>2016 Sales Dip:</strong> Conduct a thorough analysis of internal and external factors that contributed to the 2016 sales decline. This could involve scrutinizing market trends, competitor activity, internal operational challenges, or pricing strategies. Identifying the root causes will equip SuperStore with valuable knowledge to mitigate future risks.</li>
<li><strong>Growth Post-2016:</strong> Pinpoint the specific strategies implemented after 2016 that fueled the subsequent recovery and growth. This might entail analyzing marketing campaigns, product launches, customer acquisition strategies, or operational improvements. By understanding what worked well, SuperStore can double down on these successful initiatives.</li>
</ul>
<p><strong>Strategic Initiatives:</strong></p>
<ul>
<li><strong>Reinforce Successful Strategies:</strong> Amplify the impact of proven strategies by allocating additional resources, refining their execution, and scaling them to reach a wider audience. This could involve expanding marketing campaigns to new channels, investing in product development, or strengthening customer service.</li>
<li><strong>Develop Contingency Plans:</strong> Create a comprehensive plan to address potential market fluctuations or unforeseen challenges. This might include diversifying product offerings, exploring new market segments, or establishing financial reserves to weather temporary downturns.</li>
<li><strong>Continuous Monitoring and Adaptation:</strong> Establish a system for ongoing monitoring of sales performance, market trends, and competitor activities. By staying agile and adapting quickly to changing conditions, SuperStore can maintain its growth trajectory and proactively address potential risks.</li>
</ul>
<p>By proactively addressing the insights gleaned from this yearly sales analysis, SuperStore can not only sustain its current growth trajectory but also fortify its resilience against future market fluctuations, ensuring continued success in the years to come.</p>
<h4 id="heading-company-sales-analysis-charting-growth-and-uncovering-seasonal-patterns">Company Sales Analysis: Charting Growth and Uncovering Seasonal Patterns</h4>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-26.png" alt="Image" width="600" height="400" loading="lazy">
<em>Total Sales by Month from 2018 - 2019</em></p>
<p>The following analysis of SuperStore's total sales by month from 2014 to 2019 reveals a consistent upward trajectory, punctuated by seasonal fluctuations. This comprehensive view offers invaluable insights into the company's growth patterns and potential areas for optimization.</p>
<p>Key Observations:</p>
<ul>
<li><strong>Steady Growth:</strong> SuperStore has experienced a steady increase in total sales over the six-year period, reflecting positive business momentum and a growing customer base.</li>
<li><strong>Seasonal Fluctuations:</strong> Sales exhibit distinct peaks and valleys throughout the year, with the highest sales typically occurring in November and December, coinciding with holiday shopping seasons. Conversely, sales tend to dip in the first quarter of each year.</li>
<li><strong>Accelerated Growth in Later Years:</strong> The rate of sales growth appears to accelerate in the later years, particularly in 2018 and 2019, suggesting successful strategic initiatives or favorable market conditions.</li>
</ul>
<p>Actionable Insights:</p>
<ul>
<li><strong>Capitalize on Peak Seasons:</strong> Double down on marketing and promotional efforts during peak seasons to maximize revenue and capture a larger market share. Consider offering special discounts, bundles, or limited-time promotions to incentivize purchases.</li>
<li><strong>Mitigate Seasonal Dips:</strong> Develop strategies to address the sales dip in the first quarter. This could involve introducing new products or services tailored to off-season demand, offering incentives for early purchases, or focusing on customer retention and loyalty programs.</li>
<li><strong>Sustain Growth Momentum:</strong> Analyze the factors driving accelerated growth in recent years and replicate successful strategies. This could entail expanding into new markets, investing in product innovation, or optimizing marketing campaigns.</li>
<li><strong>Inventory Optimization:</strong> Utilize sales data to forecast demand accurately and adjust inventory levels accordingly, ensuring sufficient stock during peak seasons and minimizing excess inventory during slower periods.</li>
<li><strong>Data-Driven Promotions:</strong> Leverage historical sales data to create targeted promotions that align with seasonal trends and customer preferences.</li>
</ul>
<p>By meticulously examining the total sales by month and implementing these data-driven strategies, SuperStore can harness its growth potential, optimize its operations, and maintain a competitive edge in the market. This analysis empowers the company to make informed decisions that will drive continued success in the years to come.</p>
<h3 id="heading-sales-trends-1">Sales Trends</h3>
<p>The following analysis meticulously examines SuperStore's sales data across monthly, quarterly, and yearly intervals. </p>
<p>By visualizing and dissecting these temporal trends, we aim to extract actionable insights that will inform strategic decision-making, optimize sales cycles, and unlock untapped growth potential. This comprehensive assessment serves as a compass, guiding the company towards sustained revenue enhancement and a deeper understanding of the factors influencing sales performance.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-27.png" alt="Image" width="600" height="400" loading="lazy">
<em>Monthly Sales Trend from Jan 2015 to Jan 2018</em></p>
<h4 id="heading-monthly-sales-trends-seasonality-as-a-strategic-lever">Monthly Sales Trends: Seasonality as a Strategic Lever</h4>
<p>The monthly sales data reveals a clear seasonal pattern, with a pronounced peak in November and December, coinciding with the holiday shopping frenzy. This peak presents a golden opportunity for SuperStore to maximize revenue through targeted campaigns, promotions, and limited-time offers.</p>
<p>Conversely, the first quarter of each year consistently experiences a dip in sales. This predictable lull can be proactively addressed through several strategies:</p>
<ul>
<li><strong>Off-Season Product Launches:</strong> Introduce new products or services that cater specifically to customer needs during this period, such as winter clearance sales or promotions for back-to-school essentials.</li>
<li><strong>Early Bird Incentives:</strong> Incentivize early purchases through discounts, loyalty rewards, or exclusive access to new products, stimulating demand during traditionally slower months.</li>
<li><strong>Customer Retention Focus:</strong> Shift focus towards retaining existing customers through loyalty programs, personalized communication, and exceptional customer service, ensuring a steady stream of revenue even during off-peak periods.</li>
</ul>
<h4 id="heading-quarterly-sales-trends-aligning-strategy-with-seasonal-rhythms">Quarterly Sales Trends: Aligning Strategy with Seasonal Rhythms</h4>
<p>The quarterly sales data mirrors the monthly trends, highlighting the significance of Q4 (holiday season) for revenue generation and Q1 as a period for strategic adjustments. To optimize performance, SuperStore can:</p>
<ul>
<li><strong>Product Category Analysis:</strong> Analyze sales data by product category on a quarterly basis to identify seasonal trends. This enables the tailoring of product offerings and marketing campaigns to specific quarters, ensuring maximum relevance and appeal.</li>
<li><strong>Inventory Optimization:</strong> Forecast demand accurately based on historical quarterly data to avoid stockouts during peak seasons and overstocking during slower periods, thus optimizing inventory management and minimizing costs.</li>
</ul>
<h4 id="heading-yearly-sales-trends-sustaining-growth-and-mitigating-risks">Yearly Sales Trends: Sustaining Growth and Mitigating Risks</h4>
<p>The overall upward trajectory of sales over the years signifies sustained business growth, with a notable acceleration in 2018 and 2019. To maintain this momentum, SuperStore can:</p>
<ul>
<li><strong>Deep Dive into Growth Drivers:</strong> Conduct a comprehensive analysis of the factors contributing to accelerated growth, such as new product launches, market expansion, or successful marketing initiatives. Replicating these successes can further propel the company's upward trajectory.</li>
<li><strong>Continuous Optimization:</strong> Implement data-driven strategies to refine marketing campaigns, enhance customer experiences, and streamline operations. By continuously monitoring key performance indicators (KPIs) and adapting to market dynamics, SuperStore can ensure continued growth and profitability.</li>
<li><strong>Risk Mitigation:</strong> Develop contingency plans to address potential risks and unforeseen challenges, such as economic downturns or shifts in consumer behavior. This could involve diversifying revenue streams, expanding into new markets, or building financial reserves to weather turbulent periods.</li>
</ul>
<p>The sales trends analysis paints a vivid picture of SuperStore's growth trajectory and seasonal fluctuations. By leveraging these insights and implementing proactive strategies, the company can optimize its operations, capitalize on seasonal opportunities, and navigate challenges with agility. This data-driven approach ensures that SuperStore remains not only responsive to market dynamics but also well-positioned for sustained growth and continued success in the years to come.</p>
<h3 id="heading-total-sales-by-us-state">Total Sales by U.S. State</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-28.png" alt="Image" width="600" height="400" loading="lazy">
<em>The choropleth map of the total sales by U.S. State</em></p>
<p>The choropleth map of the United States provides a vivid illustration of total sales distribution by state, revealing significant variances in market performance across the country. This geographical visualization is instrumental for identifying key markets, underperformers, and potential growth opportunities.</p>
<h4 id="heading-high-performance-states">High-Performance States</h4>
<p>The map highlights California, Texas, and New York as the top-performing states with the highest sales volumes, marked by deeper shades. These states, known for their large populations and robust economies, naturally present lucrative markets for our products.</p>
<ul>
<li><strong>California</strong>: Stands out as the highest revenue generator, suggesting strong market penetration and customer engagement.</li>
<li><strong>New York and Texas</strong>: Follow closely, indicating well-established markets with considerable consumer spending.</li>
</ul>
<h4 id="heading-mid-level-and-emerging-markets">Mid-Level and Emerging Markets</h4>
<p>States such as Florida and Illinois are depicted in mid-range colors, indicating moderate sales volumes. These regions hold potential for growth and may benefit from targeted marketing strategies and increased distribution efforts.</p>
<ul>
<li><strong>Florida</strong>: Shows potential as an emerging market that could be tapped more effectively through localized marketing campaigns and possibly expanding the distribution network.</li>
<li><strong>Illinois</strong>: Suggests a stable market presence that could be enhanced by exploring consumer preferences and adjusting product offerings to better meet local demands.</li>
</ul>
<h4 id="heading-lower-sales-regions">Lower Sales Regions</h4>
<p>The map also identifies several states, particularly in the central and mountain regions, where sales are relatively low. These areas require a strategic approach to determine whether the low sales are due to poor market penetration, lack of consumer awareness, or other factors.</p>
<ul>
<li><strong>Central and Mountain States</strong>: Such as Montana, Wyoming, and the Dakotas, show minimal sales, which could be addressed by investigating local market conditions and possibly increasing marketing efforts.</li>
</ul>
<h4 id="heading-strategic-implications-1">Strategic Implications</h4>
<p>The geographic sales analysis reveals a diverse landscape with distinct opportunities and challenges across various regions. By leveraging these insights and implementing a multi-pronged strategic approach, SuperStore can optimize its market penetration and sales performance.</p>
<h4 id="heading-high-performance-states-sustained-dominance-and-strategic-expansion">High-Performance States: Sustained Dominance and Strategic Expansion</h4>
<p>In high-performing states like California, New York, and Texas, where SuperStore has already established a strong foothold, the focus shifts towards sustaining dominance and exploring avenues for further growth.</p>
<p><strong>Actionable Strategies:</strong></p>
<ol>
<li><strong>Invest in Customer Retention:</strong> Implement loyalty programs, personalized offers, and exceptional customer service to maintain and strengthen relationships with existing customers, ensuring repeat business and positive word-of-mouth.</li>
<li><strong>Expand Product Lines:</strong> Introduce new product lines or variations that cater to the specific preferences and demographics of these high-value markets, tapping into unmet needs and increasing average order value.</li>
<li><strong>Vertical Integration:</strong> Explore opportunities for vertical integration within the supply chain to reduce costs, improve efficiency, and enhance control over product quality and distribution.</li>
<li><strong>Horizontal Expansion:</strong> Consider acquiring or partnering with complementary businesses in these regions to expand market reach, access new customer segments, and diversify revenue streams.</li>
</ol>
<h4 id="heading-mid-level-states-targeted-growth-and-market-penetration">Mid-Level States: Targeted Growth and Market Penetration</h4>
<p>States like Florida and Illinois represent promising markets with moderate sales volumes and untapped potential. A targeted approach is necessary to increase brand visibility and drive customer engagement.</p>
<p><strong>Actionable Strategies:</strong></p>
<ol>
<li><strong>Localized Marketing Campaigns:</strong> Develop marketing campaigns tailored to the specific preferences and demographics of each state. Leverage local influencers, community partnerships, and regional events to create a sense of connection and resonance with the target audience.</li>
<li><strong>Competitive Analysis:</strong> Conduct a thorough analysis of the competitive landscape in these states to identify gaps in the market and differentiate SuperStore's offerings. Focus on unique value propositions and competitive pricing to attract new customers.</li>
<li><strong>Distribution Channel Optimization:</strong> Evaluate and optimize distribution channels to ensure efficient product delivery and availability across all retail locations and online platforms.</li>
<li><strong>Customer Feedback Loop:</strong> Establish a mechanism for gathering and analyzing customer feedback to understand regional preferences, identify areas for improvement, and tailor product offerings to meet specific needs.</li>
</ol>
<h4 id="heading-underperforming-markets-strategic-assessment-and-targeted-interventions">Underperforming Markets: Strategic Assessment and Targeted Interventions</h4>
<p>States with low sales volumes, particularly those in the central and mountain regions, require a nuanced approach to understand the root causes of underperformance and develop targeted interventions.</p>
<p><strong>Actionable Strategies:</strong></p>
<ol>
<li><strong>Market Research:</strong> Conduct in-depth market research to identify barriers to entry or performance, including competitor analysis, consumer behavior studies, and assessments of local economic conditions.</li>
<li><strong>Strategic Partnerships:</strong> Explore partnerships with local businesses or distributors to expand market reach, leverage existing networks, and gain insights into regional nuances.</li>
<li><strong>Localized Promotions:</strong> Launch targeted promotions and discounts to raise brand awareness and incentivize trial purchases.</li>
<li><strong>Product Localization:</strong> Consider adapting product lines or services to meet the unique needs and preferences of consumers in these regions.</li>
</ol>
<p>By embracing a data-driven approach to geographic analysis and implementing these targeted strategies, SuperStore can optimize its sales performance across all U.S. states. </p>
<p>This involves a combination of reinforcing success in high-performing areas, accelerating growth in mid-level markets, and strategically addressing challenges in underperforming regions. </p>
<p>The ultimate goal is to create a sustainable growth trajectory that leverages the strengths of each market while mitigating risks and maximizing profitability across the entire United States.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As we conclude our comprehensive analysis of the SuperStore dataset, it's evident that the ability to harness and interpret vast amounts of data can dramatically transform business outcomes. </p>
<p>Through strategic data analysis, we've unlocked insights across customer segmentation, sales trends, geographical performance, and product dynamics, providing actionable intelligence that can drive substantial improvements in marketing efficiency, customer engagement, and overall profitability.</p>
<h3 id="heading-empowering-data-driven-decision-making">Empowering Data-Driven Decision Making</h3>
<p>The insights derived from the SuperStore dataset underline the importance of a nuanced approach to customer segmentation. They reveal that while consumers form the bulk of our customer base and contribute significantly to sales, segments like Corporate and Home Office offer substantial revenue per transaction. </p>
<p>This differentiation enables the tailoring of marketing strategies and product offerings to meet the distinct needs of each segment, optimizing resources and maximizing impact.</p>
<h3 id="heading-optimizing-sales-and-marketing-strategies">Optimizing Sales and Marketing Strategies</h3>
<p>Our analysis has highlighted key sales trends and seasonal fluctuations that are crucial for planning and resource allocation. By understanding the periodicity in sales, SuperStore can better manage inventory, tailor promotions, and adjust pricing strategies to capitalize on peak times and mitigate slow periods. </p>
<p>Also, the geographical analysis provided a roadmap for regional focus, identifying high-potential markets for expansion and regions requiring targeted interventions to enhance performance.</p>
<h3 id="heading-product-analysis-for-strategic-growth">Product Analysis for Strategic Growth</h3>
<p>The product category analysis has not only identified top-performing and underperforming categories but also offered insights into customer preferences and market trends. </p>
<p>This knowledge is invaluable for driving innovation, streamlining product portfolios, and crafting marketing messages that resonate with target audiences, thereby fostering customer loyalty and attracting new clients.</p>
<h3 id="heading-future-steps-for-implementation">Future Steps for Implementation</h3>
<p>To build on the findings from our analysis, the following steps are recommended:</p>
<ol>
<li><strong>Integrate Advanced Analytics</strong>: Implement machine learning models and predictive analytics to refine customer segmentation and anticipate market trends, enhancing the ability to act proactively rather than reactively.</li>
<li><strong>Enhance Customer Experience</strong>: Develop a personalized engagement strategy that leverages data insights to deliver customized communications, promotions, and product recommendations that speak directly to the needs and preferences of each segment.</li>
<li><strong>Expand Geographical Reach</strong>: Use the insights from the geographical analysis to strategically enter new markets and optimize presence in underperforming regions, possibly through partnerships or localized marketing efforts.</li>
<li><strong>Continuous Improvement</strong>: Establish a culture of continuous learning and adaptation, using ongoing data analysis to refine strategies and operations, ensuring that SuperStore remains agile and responsive to changing market dynamics.</li>
</ol>
<p>This journey through the SuperStore dataset has not only underscored the critical role of data in modern business environments but has also illuminated a path toward data-driven decision-making that empowers organizations to thrive. </p>
<p>By meticulously examining various facets of the business, from customer segmentation and sales trends to product categories and geographical analysis, we've unearthed a wealth of insights that can inform strategic initiatives and drive growth.</p>
<p>I extend my heartfelt gratitude to the freeCodeCamp team for their invaluable support, and to Kaggle for providing the rich dataset and example code for some sections that served as the foundation for this exploration.</p>
<p>For anyone seeking to harness the power of data to optimize business strategies and make informed decisions, this project serves as a shining example. I've thoroughly enjoyed delving into the intricacies of SuperStore's data and believe that this analysis can serve as an inspiration and a practical guide for anyone embarking on a similar journey. </p>
<p>By applying the techniques and methodologies outlined here, businesses of all sizes can gain a competitive edge, enhance customer satisfaction, and achieve sustainable growth in today's data-driven landscape.</p>
<h2 id="heading-about-the-author"><strong>About the Author</strong></h2>
<p>Vahe Aslanyan here, at the nexus of computer science, data science, and AI. Visit <a target="_blank" href="https://www.freecodecamp.org/news/p/61bdcc92-ed93-4dc6-aeca-03b14c584b30/vaheaslanyan.com">vaheaslanyan.com</a> to see a portfolio that's a testament to precision and progress. My experience bridges the gap between full-stack development and AI product optimization, driven by solving problems in new ways.</p>
<p>With a track record that includes launching a <a target="_blank" href="https://www.freecodecamp.org/news/p/ad4edb43-532a-430e-82b2-1fb2558b7f73/lunartech.ai">leading data science bootcamp</a> and working with industry top-specialists, my focus remains on elevating tech education to universal standards.</p>
<h3 id="heading-how-can-you-dive-deeper">How Can You Dive Deeper?</h3>
<p>After studying this guide, if you're keen to dive even deeper and structured learning is your style, consider joining us at <a target="_blank" href="https://lunartech.ai/"><strong>LunarTech</strong></a>, we offer individual courses and Bootcamp in Data Science, Machine Learning and AI.</p>
<p>We provide a comprehensive program that offers an in-depth understanding of the theory, hands-on practical implementation, extensive practice material, and tailored interview preparation to set you up for success at your own phase.</p>
<p>You can check out our <a target="_blank" href="https://lunartech.ai/course-overview/">Ultimate Data Science Bootcamp</a> and join <a target="_blank" href="https://lunartech.ai/pricing/">a free trial</a> to try the content first hand. This has earned the recognition of being one of the <a target="_blank" href="https://www.itpro.com/business-strategy/careers-training/358100/best-data-science-boot-camps">Best Data Science Bootcamps of 2023</a>, and has been featured in esteemed publications like <a target="_blank" href="https://www.forbes.com.au/brand-voice/uncategorized/not-just-for-tech-giants-heres-how-lunartech-revolutionizes-data-science-and-ai-learning/">Forbes</a>, <a target="_blank" href="https://finance.yahoo.com/news/lunartech-launches-game-changing-data-115200373.html?guccounter=1&amp;guce_referrer=aHR0cHM6Ly93d3cuZ29vZ2xlLmNvbS8&amp;guce_referrer_sig=AQAAAAM3JyjdXmhpYs1lerU37d64maNoXftMA6BYjYC1lJM8nVa_8ZwTzh43oyA6Iz0DfqLtjVHnknO0Zb8QTLIiHuwKzQZoodeM85hkI39fta3SX8qauBUsNw97AeiBDR09BUDAkeVQh6eyvmNLAGblVj3GSf1iCo81bwHQxknmhgng#">Yahoo</a>, <a target="_blank" href="https://www.entrepreneur.com/ka/business-news/outpacing-competition-how-lunartech-is-redefining-the/463038">Entrepreneur</a> and more. This is your chance to be a part of a community that thrives on innovation and knowledge.  Here is the Welcome message!</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/c-SXFXegVTw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-connect-with-me"><strong>Connect with Me</strong></h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/05/image-29.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://substack.com/@lunartech">LunarTech </a>Newsletter</em></p>
<p><strong>Connect with Me:</strong></p>
<ul>
<li><a target="_blank" href="https://ca.linkedin.com/in/vahe-aslanyan">Follow me on LinkedIn for a ton of Free Resources in CS, ML and AI</a></li>
<li><a target="_blank" href="https://vaheaslanyan.com/">Visit my Personal Website</a></li>
<li>Subscribe to my <a target="_blank" href="https://tatevaslanyan.substack.com/">The Data Science and AI Newsletter</a></li>
</ul>
<p>If you want to learn more about a career in Data Science, Machine Learning and AI, and learn how to secure a Data Science job, you can download this free <a target="_blank" href="https://downloads.tatevaslanyan.com/six-figure-data-science-ebook">Data Science and AI Career Handbook</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn the C# Programming Language – Full Book for Beginners ]]>
                </title>
                <description>
                    <![CDATA[ C# version 1 was released in January 2002. It is a modern, general purpose programming language designed and developed from the ground up by the renowned Danish software engineer, Anders Heijleberg and his team at Microsoft. I’ve heard Anders Heijlsb... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-csharp-book/</link>
                <guid isPermaLink="false">66b0c58dece58de64f5e1dc9</guid>
                
                    <category>
                        <![CDATA[ beginner ]]>
                    </category>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ C# ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Gavin Lon ]]>
                </dc:creator>
                <pubDate>Tue, 06 Feb 2024 22:35:57 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/02/The-C--Handbook---Version-4-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>C# version 1 was released in January 2002. It is a modern, general purpose programming language designed and developed from the ground up by the renowned Danish software engineer, Anders Heijleberg and his team at Microsoft.</p>
<p>I’ve heard Anders Heijlsberg say in an interview that with C# the goal was to provide the power and expressiveness of C++ and the RAD (Rapid Application Development) capabilities of Visual Basic.</p>
<p>C# is similar to Java in the sense that it runs within its own environment. Java runs within an environment known as the JRE (Java Runtime Environment) whereas C# runs in an environment known as .NET. Both the JRE and .NET run on top of the relevant operating system.</p>
<p>The first version of .NET is known as the .NET Framework which needs to be deployed to the target computer in its entirely and can only run on Windows platforms. But now, .NET has evolved into an environment that can run on multiple platforms like Windows, Mac OS, Linux, IOS, Android and more.</p>
<p>The .NET environment became fragmented in 2016 with the release of .NET Core, which enabled .NET to be cross platform and agile in the sense that only your application’s base class library dependencies need to be deployed to the target computer with your application.</p>
<p>Then in 2020, .NET became unified with the release of NET 5, which meant that the confusion created by having two strands of .NET, namely .NET Framework and .NET Core, was alleviated.</p>
<p>The latest stable release of C# is a highly evolved, sophisticated programming language that allows you to create almost any kind of application that can run on multiple platforms. You can create a single code base that can run on multiple platforms, for example Linux, Mac OS, Android, IOS, in the Cloud, of course Windows operating systems and more.</p>
<p>You are able to write and build your C# applications using free tools like Visual Studio 2022 Community edition or the cross platform, light weight tool, Visual Studio Code. Visual Studio Code can run on Windows, Mac OS, and Linux platforms.</p>
<p>C# is a highly versatile programming language. You can build many types of applications, such as web-based applications using ASP .NET, cross platform mobile and desktop applications using the .Net MAUI framework, Internet of things applications, AI applications using ML.NET, cloud native applications, games and more.</p>
<p>C# has a huge support base, backed by Microsoft, and is constantly evolving. A new version of .NET is shipped every November, which always contains many improvements and enhancements. This means that .NET is forever evolving, improving, and keeping up with the latest trends in technology.</p>
<p>C# is a well designed, modern, general purpose programming language that will be a great addition to your developer toolkit. So let's dive in.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-introduction-to-net">Introduction to .NET</a></li>
<li><a class="post-section-overview" href="#heading-free-tools-available-for-creating-c-applications">Free Tools Available for Creating C# Applications</a><ul>
<li><a class="post-section-overview" href="#heading-create-a-basic-console-app-using-visual-studio-community-edition">Create a Basic Console App using Visual Studio Community Edition</a><ul>
<li><a class="post-section-overview" href="#heading-the-main-method-application-entry-point">The Main Method (Application Entry Point)</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-basic-console-app-using-visual-studio-code">Creating a Basic Console App using Visual Studio Code</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-data-types">C# Data Types</a><ul>
<li><a class="post-section-overview" href="#heading-value-types-and-reference-types">Value Types and Reference Types</a></li>
<li><a class="post-section-overview" href="#heading-c-built-in-value-types">C# Built-in Value Types</a></li>
<li><a class="post-section-overview" href="#heading-c-built-in-reference-types">C# Built-in Reference Types</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-strings">C# Strings</a><ul>
<li><a class="post-section-overview" href="#heading-immutability-of-c-strings">Immutability of C# Strings</a></li>
<li><a class="post-section-overview" href="#heading-quoted-string-literals-verbatim-string-literals-and-raw-string-literals">Quoted String Literals, Verbatim String Literals and Raw String Literals</a><ul>
<li><a class="post-section-overview" href="#heading-quoted-string-literals">Quoted String Literals</a></li>
<li><a class="post-section-overview" href="#heading-verbatum-string-literals">Verbatum String Literals</a></li>
<li><a class="post-section-overview" href="#heading-raw-string-literals">Raw String Literals</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-useful-c-built-in-string-methods">Useful C# Built-in String Methods</a><ul>
<li><a class="post-section-overview" href="#heading-the-indexof-built-in-method">The IndexOf Built-in Method</a></li>
<li><a class="post-section-overview" href="#heading-the-replace-built-in-method">The Replace Built-in Method</a></li>
<li><a class="post-section-overview" href="#heading-the-substring-built-in-method">The Substring Built-in Method</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-data-type-conversion">C# Data Type Conversion</a><ul>
<li><a class="post-section-overview" href="#heading-implicit-vs-explicit-data-type-conversion">Implicit vs Explicit Data Type Conversion</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-operators">C# Operators</a><ul>
<li><a class="post-section-overview" href="#heading-types-of-c-operators">Types of C# Operators</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-constants-and-read-only-variables">Constants and Read-only Variables</a><ul>
<li><a class="post-section-overview" href="#heading-introduction-to-constants">Introduction to Constants</a></li>
<li><a class="post-section-overview" href="#heading-introduction-to-read-only-variables">Introduction to Read-only Variables</a></li>
<li><a class="post-section-overview" href="#heading-code-example-using-a-const">Code Example Using a Const</a></li>
<li><a class="post-section-overview" href="#heading-code-example-using-a-read-only-variable">Code Example Using a Read-only Variable</a></li>
<li><a class="post-section-overview" href="#heading-code-example-of-the-incorrect-use-of-a-read-only-variable">Code Example of the Incorrect Use of a Read-only Variable</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-if-else-if-else-statements">C# if / else if / else Statements</a><ul>
<li><a class="post-section-overview" href="#heading-basic-ifelse-conditional-logic">Basic if/else Conditional Logic</a></li>
<li><a class="post-section-overview" href="#heading-implementing-ifelse-ifelse-conditional-logic">Implementing if/else if/else Conditional Logic</a></li>
<li><a class="post-section-overview" href="#heading-nested-if-statements">Nested if Statements</a></li>
<li><a class="post-section-overview" href="#heading-more-complex-conditional-expressions">More Complex Conditional Expressions</a><ul>
<li><a class="post-section-overview" href="#heading-the-ampamp-operator">The &amp;&amp; Operator</a></li>
<li><a class="post-section-overview" href="#heading-the-operator">The || Operator</a></li>
</ul>
</li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-loops">C# Loops</a><ul>
<li><a class="post-section-overview" href="#heading-the-for-loop">The for Loop</a></li>
<li><a class="post-section-overview" href="#heading-the-while-loop">The while Loop</a></li>
<li><a class="post-section-overview" href="#heading-the-do-while-loop">The do-while Loop</a></li>
<li><a class="post-section-overview" href="#heading-the-foreach-loop">The foreach Loop</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-arrays">C# Arrays</a><ul>
<li><a class="post-section-overview" href="#heading-one-dimensional-arrays">One-dimensional Arrays</a></li>
<li><a class="post-section-overview" href="#heading-multi-dimensional-arrays">Multi-dimensional Arrays</a><ul>
<li><a class="post-section-overview" href="#heading-two-dimensional-arrays">Two-dimensional Arrays</a></li>
<li><a class="post-section-overview" href="#heading-three-dimensional-arrays">Three-dimensional Arrays</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-jagged-arrays">Jagged Arrays</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-methods">C# Methods</a><ul>
<li><a class="post-section-overview" href="#heading-introduction-to-methods-in-c">Introduction to Methods</a></li>
<li><a class="post-section-overview" href="#heading-the-main-method">The Main Method</a></li>
<li><a class="post-section-overview" href="#heading-the-structure-of-methods">The Structure of Methods</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-classes">C# Classes</a><ul>
<li><a class="post-section-overview" href="#heading-the-class-keyword">The 'class' Keyword</a></li>
<li><a class="post-section-overview" href="#heading-the-public-access-modifier">Public Access Modifier</a></li>
<li><a class="post-section-overview" href="#heading-the-private-member-variable">Private Member Variable</a></li>
<li><a class="post-section-overview" href="#heading-the-constructor">The Constructor</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-c-structs">C# Structs</a><ul>
<li><a class="post-section-overview" href="#heading-key-differences-between-a-class-and-a-struct">Key Differences Between a Class and a Struct</a></li>
<li><a class="post-section-overview" href="#heading-use-a-struct-in-code">Use a Struct in Code</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-enums-and-switch-statements">Enums and Switch Statements</a><ul>
<li><a class="post-section-overview" href="#heading-introduction-to-enums">Introduction to Enums</a></li>
<li><a class="post-section-overview" href="#heading-use-an-enum-in-code">Use an Enum in Code</a></li>
<li><a class="post-section-overview" href="#heading-using-a-switch-statement-in-code-with-an-enum">Using a switch Statement in Code with an enum</a></li>
<li><a class="post-section-overview" href="#heading-associating-one-code-block-with-more-than-one-case">Associating One Code Block with More than One Case</a></li>
<li><a class="post-section-overview" href="#heading-using-strings-in-switch-statements">Using Strings in switch Statements</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-inheritance-in-c">Inheritance in C#</a></li>
<li><a class="post-section-overview" href="#heading-abstraction-in-c">Abstraction in C#</a></li>
<li><a class="post-section-overview" href="#heading-c-exception-handling">C# Exceptions</a></li>
<li><a class="post-section-overview" href="#heading-c-delegates">C# Delegates</a></li>
<li><a class="post-section-overview" href="#heading-c-events">C# Events</a></li>
<li><a class="post-section-overview" href="#heading-c-generics">C# Generics</a></li>
<li><a class="post-section-overview" href="#heading-linq">LINQ</a></li>
<li><a class="post-section-overview" href="#heading-c-attributes">C# Attributes</a></li>
<li><a class="post-section-overview" href="#heading-reflection-in-c">Reflection</a></li>
<li><a class="post-section-overview" href="#heading-video-on-asynchronous-programming-in-c">Video on Asynchronous Programming in C#</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ul>
<h2 id="heading-introduction-to-net">Introduction to .NET</h2>
<p>As we briefly discussed in the introductory section, .NET provides an environment in which your C# applications run.</p>
<p>An essential feature of .NET is what can be described as a virtual machine known as the CoreCLR or Core Common Language Runtime.</p>
<p>The Core Common Language Runtime provides services like Just-in-time compilation, memory management, garbage collection, security and exception handling. Also provided with .NET is a variety of base class libraries, that provide generic functionality that can be leveraged by your C# code.</p>
<p>The first version of .NET was the .NET Framework which was released in 2002. .NET Framework could only run on certain windows platforms and had to be installed in its entirety on the target computer.</p>
<p>.NET Core was released in 2016 and provided a modular, cross platform version of .NET that is optimized for the cloud. A significant feature of .NET Core was that only the dependencies used by your application needed to be shipped to the target computer, unlike .NET Framework that had to exist in its entirety on the target computer.</p>
<p>The rapid evolution of these two versions of .NET, .NET Framework and .NET Core, resulted in growing fragmentations of .NET.</p>
<p>In order to deal with the continuing fragmentation of .NET, Microsoft created the .NET Standard, where all platforms running .NET had to support .NET Standard. This was the first step in unifying .NET but it was a temporary solution.</p>
<p>Then in November 2020, .NET 5 was released. This version of .NET retained the great features of both .NET Framework and .NET core, but this release was significant in that .NET 5 meant that .NET was now unified under one umbrella (as it were). There is now no more .NET Framework and .NET core – rather just one version of .NET moving forward.</p>
<p>With the release of .NET 6 the following year, in November 2021, came many significant improvements and new features. Perhaps what is most significant about .NET 6, is that it cemented the unification of .NET.</p>
<p>At this point in time, .NET is a cross platform, modular, agile, fast, robust and secure environment in which your C# applications can run. This means C# and .NET have now evolved to a point where you can “write once and run anywhere”.</p>
<p>Here's a video overview about how .NET works in more detail:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/P6lJA3E3Uog" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>And for a full video series on the evolution of .NET, you can check this out:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/OkeM7XVwEdA" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-free-tools-available-for-creating-c-applications">Free Tools Available for Creating C# Applications</h2>
<p>Microsoft provides two sophisticated free tools that you can use for creating C# applications: Visual Studio Community Edition, which is an IDE (Integrated Development Environment) that can run on Windows platforms, and Visual Studio Code (a light weight code editor) that can run on Windows, Mac OS, and Linux platforms.</p>
<p>You can download and install Visual Studio Community Edition 2022 and the latest version of Visual Studio Code from here: <a target="_blank" href="https://visualstudio.microsoft.com/downloads/">https://visualstudio.microsoft.com/downloads/</a>.</p>
<h3 id="heading-create-a-basic-console-app-using-visual-studio-community-edition">Create a Basic Console App using Visual Studio Community Edition</h3>
<p>The easiest way to create your first C# application is by using the simplest project template made available to you through Visual Studio.</p>
<p>The simplest project template is named “Console App”. To get started building your first C# application using Visual Studio, just follow the instructions below:</p>
<ul>
<li>Launch Visual Studio</li>
<li>From the “Get Started” section on the dialog presented to you, select “Create a new project”.</li>
<li>Find the project template named, “Console App”.</li>
<li>Select the “Console App” project template option and press the “Next” button.</li>
<li>Provide a name for your project and the location on your hard disk drive where you’d like to store the files for your project. Press the “Next” button.</li>
<li>At the time of the creation of this book, the latest stable release of .NET is .NET version 8. If you have this latest version installed on your target computer, it will be selected in the relevant dropdown list for the field marked “Framework”.</li>
<li>Press the ‘Create’ button to generate the files for your C# project.</li>
</ul>
<p>You can check out the YouTube video below for a demonstration of creating a basic "Console App" project using Visual Studio 2022.</p>
<p>In this YouTube video, the first demonstration of creating a basic project shows how to create a "Console App" project that includes top-level statements (that is, the <code>Main</code> method definition is not present by default).</p>
<p>The second demonstration shows the creation of a basic "Console App" project that doesn't include top-level statements. You'll see how the <code>Main</code> method is shown in the default code, whereas in the first demonstration only the body of the <code>Main</code> method is shown, and the actual <code>Main</code> method definition is not present.</p>
<p>Note that the <code>Main</code> method is always the entry point of C# applications. Where top-level-statements are included, the <code>Main</code> method is still there but is not visible by default in your code. The inclusion of top-level-statements results in a reduced amount of boilerplate code needed in order for a developer to get started.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/10QrZCLfuCQ" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h4 id="heading-the-main-method-application-entry-point">The Main Method (Application Entry Point)</h4>
<p>If you look at the "Program.cs" file, you’ll see the following code:</p>
<pre><code class="lang-csharp">
    Console.WriteLine(“Hello World”);
</code></pre>
<p>You can run this code by pressing the play button on your toolbar. The code for this application is very basic and simply outputs the line, "Hello World" to the console screen.</p>
<p>If you look at the code in the "Program.cs" file, it may seem that there is no real entry point to the application. This is specificially when you have elected to use top-level-statements. If you have written code in previous versions of .NET, the absence of a <code>Main</code> method will be conspicuous.</p>
<p>So in .NET 5, for example, the same code currently in your application would look different because the program class and within it the <code>Main</code> method would be included.</p>
<p>Check out the code depicted in figure 1 for an example of this:</p>
<p>Figure 1.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">namespace</span> <span class="hljs-title">CSharpSampleCode</span>
{
    <span class="hljs-keyword">internal</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Program</span>
    {
        <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Main</span>(<span class="hljs-params"><span class="hljs-keyword">string</span>[] args</span>)</span>
        {
            Console.WriteLine(<span class="hljs-string">"Hello, World!"</span>);
        }
    }
}
</code></pre>
<p>In .NET 6, a marked effort was made to simplify the amount of boilerplate code needed in your applications. Note that with C# 10, you can simply write the body of the <code>Main</code> method in the "Program.cs" file. You don't need to include a class definition (and within the relevant class, a <code>Main</code> method definition) as is depicted in figure 1.</p>
<p>So the relevant statements do not need to reside within a <code>Main</code> method. The statements can exist as what’s known as top-level-statements.</p>
<p>A <code>Main</code> method does still exist behind the scenes and is still the entry point for all C# applications. But after the release of .NET 6, the <code>Main</code> method does not need to be present within your code because the compiler synthesises a <code>Program</code> class with a <code>Main</code> method and places all your top-level-statements within the <code>Main</code> method.</p>
<p>But this is now done behind the scenes. The term top-level-statements means that you're able to write statements that are not wrapped in a <code>Main</code> method within a class. Behind the scenes the <code>Main</code> method and relevant class are created by the compiler. So you're able to write a lot less code, and the entry point of the application – that used to be explicitly written using the <code>Main</code> method – is now synthesised by the C# compiler.</p>
<p>Figure 2 depicts how you can avoid writing multiple lines of code for the <code>Main</code> method (the entry point for a C# application).</p>
<p>Figure 2.</p>
<pre><code class="lang-csharp">Console.WriteLine(<span class="hljs-string">"Hello, World!"</span>); <span class="hljs-comment">//The ‘Main' method is not visible within the code</span>
</code></pre>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/2pquQMSYk6c" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h3 id="heading-how-to-create-a-basic-console-app-using-visual-studio-code">How to Create a Basic Console App using Visual Studio Code</h3>
<p>I'll now walk you through the process of creating a console application using Visual Studio Code.</p>
<p>First, you'll need to launch VS Code. For the best experience coding an application in C#, you should install the C# Dev Kit extension using the Extensions view.</p>
<p>You can bring up the Extensions view by clicking the Activity Bar on the side of Visual Studio Code. You can then search for C# Dev Kit and install this extension.</p>
<p>Next, create a local folder where you’d like to store the files for your C# project anywhere on your computer.</p>
<p>Using the File &gt; Open Folder menu option, open the folder you created in the previous step, from within VS Code.</p>
<p>Then launch the terminal window using the View &gt; Terminal menu option. You can also launch the terminal window by pressing ctrl + `</p>
<p>You’ll need to ensure that you have installed an appropriate version of the .NET SDK. The latest stable release is .NET version 8. You can download the recommended install file from this location, <a target="_blank" href="https://dotnet.microsoft.com/download">https://dotnet.microsoft.com/download</a>.</p>
<p>In order to verify that you have installed the .NET SDK, you can type <code>dotnet —-version</code> within the terminal window and then press the enter key.</p>
<p>To create a project based on the "Console App" project template, you can type this command at your command prompt: <code>dotnet new console</code>. Then press the enter key.</p>
<p>To run the project, type <code>dotnet run</code> at the command prompt and press the enter key.</p>
<p>After you have appropriately updated the code in your 'Program.cs' file, remember to save your changes before running the updated code.</p>
<p>As an exercise, change the the code so that the output is 'Hello C#', then save your code, and then run your code by typing in, <code>dotnet run</code> in the terminal window. Once you press the enter key, 'Hello C#' should be outputted to your console screen.</p>
<p>For a detailed video guide on how to use Visual Studio Code to create C# applications, you can watch the following YouTube video:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/rab_1cFQUF4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-c-data-types">C# Data Types</h2>
<p>It's important to note that C# is a statically typed programming language, whereas JavaScript and Python, for example, are both dynamically typed.</p>
<p>This means that in C#, when variables are declared at compile time, the variables must be defined as a specific C# type.</p>
<p>An exception to this rule is made through the use of the <code>dynamic</code> type. The <code>dynamic</code> data type allows you to circumvent the .Net type system. If a variable is declared as the <code>dynamic</code> data type, this is similar to how variables are typed in a dynamically typed language like JavaScript.</p>
<p>In most cases, you should strongly type variables so that you can reap the benefits inherent in a statically typed language. The advantage of strongly typing variables is that potential data type-related errors can be flagged at compiled time and then dealt with appropriately at compile time.</p>
<p>If you create code that is not valid in relation to the type used to define a variable, this can be flagged by the C# compiler at compile time.</p>
<p>If you look at the code example in figure 3, the C# code is invalid because variable <code>a</code> is defined as an integer and in the <code>DoSomething</code> method, the <code>a</code> variable is assigned a string value.</p>
<p>The C# compiler flags the exception at compile time, and the exception is represented within the Visual Studio IDE, where a red squiggly line is drawn under the offending code.</p>
<p>Figure 3.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">internal</span> <span class="hljs-keyword">class</span> <span class="hljs-title">SomeClass</span>
{
    <span class="hljs-keyword">int</span> a = <span class="hljs-number">1</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">DoSomething</span>(<span class="hljs-params"></span>)</span>
    {
        a = <span class="hljs-string">"Gavin Lon"</span>; <span class="hljs-comment">// Compile time error stating: "Cannot implicitly convert type 'string' to 'int'"</span>
    }
}
</code></pre>
<p>So the code fails to compile and the cause of the compile time exception is made clear to you through a red squiggly line which appears under the offending code.</p>
<p>This safeguards type-related exceptions from being deployed to a production environment where code that is not appropriately checked at compile time could be prone to runtime errors.</p>
<p>Statically typed languages ensure better code robustness at runtime than dynamically typed languages. C# also performs better than dynamically typed languages like JavaScript or Python because the use of statically typed variables means that the type of the variable is known at compile time. This means that variable types do not need to be determined at runtime, which is what happens with dynamically typed languages.</p>
<p>With dynamically typed languages, the type of a variable is determined at runtime based on the value assigned to the relevant variable. With statically typed languages like C#, the type is known, as it were, at compile time – so the added step of determining the variable's type at runtime is not necessary. This results a performance advantage over dynamically typed code.</p>
<h3 id="heading-value-types-and-reference-types">Value Types and Reference Types</h3>
<p>C# data types can be put into two main classifications: value types and reference types. These main data type classifications denote how data for C# data types are stored in memory.</p>
<p>A value type is stored in a memory location called the stack, where the value assigned to a variable is stored in the relevant memory space on the stack.</p>
<p>A reference type is stored in a memory location known as the heap, where an address of where the actual data is stored resides on the stack and points to the location where the actual data is stored on the heap.</p>
<p>A key difference between data stored on the stack and data stored on the heap is that all data stored on the stack has a fixed size, where data stored on the heap does not have a fixed size. the fixed size for discrete data stored on the stack means more efficiency in the storage and retrieval of such data when compared to the management of data stored on the heap.</p>
<p>A very basic example that highlights the significance of value types and references types is the following:</p>
<p>Let’s say an integer named <code>a</code> is assigned a value of <code>1</code>, and an integer named <code>b</code> is assigned the value stored in <code>a</code>. Then let’s say that the value of <code>3</code> is assigned to variable <code>a</code>. Does this assignment affect the value stored in variable <code>b</code>?</p>
<p>The answer is no. This is because the integer data type is a value type. The <code>a</code> variable’s data and the <code>b</code> variable’s data are stored in completely different memory locations on the stack. So a change to the data stored in variable <code>a</code> will not affect the data stored in variable <code>b</code>, even though the value stored in <code>a</code> was assigned to the <code>b</code> variable.</p>
<p>Figure 4.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span> a = <span class="hljs-number">1</span>;
<span class="hljs-keyword">int</span> b = a;
a = <span class="hljs-number">3</span>;
</code></pre>
<p>The object data type in C# is the root type for all data types in C#. An object data type is a reference type, and so all types that inherit directly from the object data type are reference types.</p>
<p>In the example below (in figure 5), variable <code>a</code>, which is defined as the <code>Employee</code> user defined type, is assigned a new <code>Employee</code> object, where the <code>Name</code> property is set to the string value of <code>"Gavin Lon"</code>. Variable <code>b</code>, which is defined as the <code>Employee</code> user defined type, is assigned the value of <code>a</code>.</p>
<p>When the <code>Name</code> property of object variable <code>a</code> is changed to <code>David Hasslehoff</code>, the <code>Name</code> property of object variable <code>b</code> is automatically changed to <code>"David Hasslehof"</code>.</p>
<p>This is because when <code>b</code> is assigned the value stored in <code>a</code>, the data stored in <code>a</code> is not copied to the storage location that stores the data in <code>b</code>. A memory address is copied to <code>b</code>, which contains the memory location of where the data is stored for variable <code>a</code>. The actual data is stored on the heap and only the memory location of where the data is stored on the heap, is stored on the stack.</p>
<p>This means that variable <code>a</code> and variable <code>b</code> reference the same data (stored on the heap) at this point. So when the <code>Name</code> property of object variable <code>a</code> is changed to <code>"David Hasslehof"</code>, this change also affects variable <code>b</code>. So the <code>Name</code> property in variable <code>b</code> will also reflect <code>"David Hasselhof"</code>.</p>
<p>Figure 5.</p>
<pre><code class="lang-csharp">Employee a = <span class="hljs-keyword">new</span> Employee { Id = <span class="hljs-number">1</span>, Name = <span class="hljs-string">"Gavin Lon"</span> };
Employee b = a;
a.Name = <span class="hljs-string">"David Hasslehof"</span>;
Console.WriteLine(b.Name); <span class="hljs-comment">// This code prints out the value of David Hasslehof</span>
</code></pre>
<h3 id="heading-c-built-in-value-types">C# Built-in Value Types</h3>
<p>You can see below, in figure 6, the built-in value type data types in C#. Each item contains a link to an appropriate Microsoft Learn page so that you can read more about the relevant data type.</p>
<p>Figure 6.</p>
<table><thead><tr><th>C# type keyword</th><th>.NET type</th></tr></thead><tbody><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/bool"><code>bool</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.boolean" class="no-loc">System.Boolean</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>byte</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.byte" class="no-loc">System.Byte</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>sbyte</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.sbyte" class="no-loc">System.SByte</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/char"><code>char</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.char" class="no-loc">System.Char</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types"><code>decimal</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.decimal" class="no-loc">System.Decimal</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types"><code>double</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.double" class="no-loc">System.Double</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/floating-point-numeric-types"><code>float</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.single" class="no-loc">System.Single</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>int</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.int32" class="no-loc">System.Int32</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>uint</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.uint32" class="no-loc">System.UInt32</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>nint</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.intptr" class="no-loc">System.IntPtr</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>nuint</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.uintptr" class="no-loc">System.UIntPtr</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>long</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.int64" class="no-loc">System.Int64</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>ulong</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.uint64" class="no-loc">System.UInt64</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>short</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.int16" class="no-loc">System.Int16</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/integral-numeric-types"><code>ushort</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.uint16" class="no-loc">System.UInt16</a></td></tr></tbody></table>

<h3 id="heading-c-built-in-reference-types">C# Built-in Reference Types</h3>
<p>And you can also see all of the built-in reference type data types in C# in figure 7.</p>
<p>Figure 7.</p>
<table><thead><tr><th>C# type keyword</th><th>.NET type</th></tr></thead><tbody><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types#the-object-type"><code>object</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.object" class="no-loc">System.Object</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types#the-string-type"><code>string</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.string" class="no-loc">System.String</a></td></tr><tr><td><a href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/builtin-types/reference-types#the-dynamic-type"><code>dynamic</code></a></td><td><a href="https://learn.microsoft.com/en-us/dotnet/api/system.object" class="no-loc">System.Object</a></td></tr></tbody></table>

<p>And now you can check out two YouTube videos where C# data types and C# variables are discussed. Code examples are also provided.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/sW-fsSJaFA0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/rM9HostBLJ4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-c-strings">C# Strings</h2>
<p>In C#, you can define a string using the <code>System.String</code> class or using its alias, <code>string</code>. In the example depicted in figure 8, the two lines of code are equivalent:</p>
<p>Figure 8.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> fullName = <span class="hljs-string">"Gavin Lon"</span>;
System.String fullName = <span class="hljs-string">"Gavin Lon"</span>;
</code></pre>
<p>A string is simply a reference to an object in memory that stores text. Internally, a string is an array of char objects.</p>
<p>To create a new string object, the <code>new</code> keyword is not generally used. The <code>new</code> keyword is only used to create a new string when an array of char objects is passed as an argument to the constructor of the relevant string object.</p>
<p>You can see an example of this below in figure 9.</p>
<p>Figure 9.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">char</span>[] nameCharacters = { <span class="hljs-string">'G'</span>, <span class="hljs-string">'a'</span>, <span class="hljs-string">'v'</span>, <span class="hljs-string">'i'</span>, <span class="hljs-string">'n'</span>, <span class="hljs-string">' '</span>, <span class="hljs-string">'L'</span>, <span class="hljs-string">'o'</span>, <span class="hljs-string">'n'</span> };
<span class="hljs-keyword">string</span> fullName = <span class="hljs-keyword">new</span> <span class="hljs-keyword">string</span>(nameCharacters);
</code></pre>
<h3 id="heading-immutability-of-c-strings">Immutability of C# Strings</h3>
<p>Strings are reference types, which means a numeric reference to a memory address is stored on the stack and points to the actual string data which is stored on the heap.</p>
<p>The difference between the string reference type and other reference types (like, for example, an object instantiated from a class) is that the data for a particular string (stored on the heap) cannot be directly changed in memory. This means that every time, for example, a concatenation operation occurs in code, the memory address stored on the stack is simply amended to point to a new memory location on the heap that stores the new string that has been created as a result of the relevant concatenation operation.</p>
<h3 id="heading-quoted-string-literals-verbatim-string-literals-and-raw-string-literals">Quoted String Literals, Verbatim String Literals and Raw String Literals</h3>
<h4 id="heading-quoted-string-literals">Quoted String Literals</h4>
<p>Quoted string literals are string values defined on one line in code that start with a single double quote character and end with a single double quote character. Quoted string literals are best suited for stings that exist on one line and don’t contain escape sequences.</p>
<p>If you were to include a backslash (<code>\</code>) character in a quoted string literal (like when expressing a directory path, for example), you would need to escape the backslash character with a backslash character directly preceding the backslash character you wish to output as part of the string.</p>
<p>Here's an example of this depicted in figure 11.</p>
<p>Figure 11.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> path = <span class="hljs-string">"C:\\development\\CSharpProjects"</span>;
Console.Write(path);
<span class="hljs-comment">// Output: C:\development\CSharpProjects</span>
</code></pre>
<p>The <code>\</code> character has a special meaning in C#, so it must be escaped with the appropriate escape character – which is the <code>\</code> character. To make it clear that the <code>\</code> character is an escape character used in C# string literals, see the below example (in figure 12) where the <code>\</code> character is used to escape the double quote (<code>"</code>) characters included in a string literal.</p>
<p>Figure 12.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> path = <span class="hljs-string">"\"C:\\development\\CSharpProjects\""</span>;
Console.WriteLine(path);
<span class="hljs-comment">//Output: "C:\development\CSharpProjects"</span>
</code></pre>
<h4 id="heading-verbatum-string-literals">Verbatum String Literals</h4>
<p>Verbatim string literals are recommended where quotations and backslash characters need to be included in the output for string literals. If you precede a string literal with the <code>@</code> symbol, the relevant code can output the relevant string verbatim.</p>
<p>Note how the code in figure 13 outputs the same result as the code depicted in figure 12.</p>
<p>Figure 13.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> path = <span class="hljs-string">@"""C:\development\CSharpProjects"""</span>;
Console.WriteLine(path);
<span class="hljs-comment">// Output: "C:\development\CSharpProjects"</span>
</code></pre>
<p>The output is the same when the same string lateral is represented in code as a quoted string literal and as a verbatim string literal.</p>
<p>But using a verbatim string literal is much easier to read and is cleaner in its representation. So where the backslash and double quote symbols need to be outputted within the string literal, it's better to use a verbatim string literal.</p>
<p>It's also better to use a verbatim string literal for code that outputs multiline text. In figure 14 is a code example where a verbatim string literal is used in code to output multiline text.</p>
<p>Figure 14.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> narrative =
    <span class="hljs-string">@"Humpty Dumpty sat on the wall
Humpty Dumpty had a great fall
all the kings horses and all the kings men
couldn’t put Humpty together again"</span>;
</code></pre>
<p>So the above code example dipicted in figure 14 would output the narrative as it is written in the literal string – that is, the text is outputted on multiple lines as the text appears within the literal string in code.</p>
<h4 id="heading-raw-string-literals">Raw String Literals</h4>
<p>C# 11 introduced raw string literals. These make it even easier to write code to output multiline text.</p>
<p>Raw string literals remove the need to ever use escape sequences within literal strings.</p>
<p>To indicate in code that you are using a raw string literal, you wrap the relevant text in three double quote symbols. So the first 3 characters should be three double quote symbols followed by the literal string, and the last 3 characters must be three double quote symbols.</p>
<p>Note that in this example, the three quotes that wrap the string literal appear on their own line. This is important because in this example the first part of the string literal appears within double quotes.</p>
<p>Note the output of the code below in figure 15.</p>
<p>Figure 15.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> text = <span class="hljs-string">""</span><span class="hljs-string">"
"</span>To be or not to be<span class="hljs-string">" is a quote from Shakespeare's Hamlet.
"</span><span class="hljs-string">""</span>;
Console.WriteLine(text);
<span class="hljs-comment">// Output: "To be or not to be" is a quote from Shakespeare’s Hamlet.</span>
</code></pre>
<p>Note the output of the code example depicted in figure 16.</p>
<p>Figure 16.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> path = <span class="hljs-string">""</span><span class="hljs-string">"C:\development\CSharpProjects"</span><span class="hljs-string">""</span>;
Console.WriteLine(path);
<span class="hljs-comment">// Output: C:\development\CSharpProjects</span>
</code></pre>
<p>You could output the multiline text shown in the code example in figure 17, where the output is displayed to the screen in much the same way as the text is represented over multiple lines in the relevant raw literal string in code.</p>
<p>Note that when using a raw string literal to output multiple lines of text, the three double quote characters that must be used to wrap the relevant multiline text must each be on their own line, as is depicted in the example in figure 17.</p>
<p>Figure 17.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> narrative = <span class="hljs-string">""</span><span class="hljs-string">"
Humpty Dumpty sat on the wall
Humpty Dumpty had a great fall
all the kings horses and all the kings men
couldn’t put Humpty together again
"</span><span class="hljs-string">""</span>;
</code></pre>
<h2 id="heading-useful-c-built-in-string-methods">Useful C# Built-in String Methods</h2>
<p>The C# language has many useful built-in string methods that can, for example, be leveraged for common string-related functionality.</p>
<h3 id="heading-the-indexof-built-in-method">The IndexOf Built-in Method</h3>
<p>One common example is finding a string literal within text stored within a string variable using the <code>IndexOf</code> method. See the code example of this depicted in figure 18.</p>
<p>Figure 18.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> narrative = <span class="hljs-string">"Gavin Lon loves to create free courses on the freeCodeCamp YouTube channel."</span>;

<span class="hljs-comment">// find freeCodeCamp in the narrative</span>
<span class="hljs-keyword">var</span> indx = narrative.IndexOf(<span class="hljs-string">"freeCodeCamp"</span>);

<span class="hljs-comment">// the value of indx will be 46</span>
<span class="hljs-keyword">if</span> (indx == <span class="hljs-number">-1</span>)
{
    Console.WriteLine(<span class="hljs-string">"\"freeCodeCamp\" could not be found in the narrative"</span>);
}
<span class="hljs-keyword">else</span>
{
    Console.WriteLine(<span class="hljs-string">$"\"freeCodeCamp\" was found at position <span class="hljs-subst">{indx}</span> in the narrative"</span>);
}
indx = narrative.IndexOf(<span class="hljs-string">"Gavin Lon"</span>);

<span class="hljs-comment">// the value of indx will be 0</span>
<span class="hljs-keyword">if</span> (indx == <span class="hljs-number">-1</span>)
{
    Console.WriteLine(<span class="hljs-string">"\"Gavin Lon\" could not be found in the narrative"</span>);
}
<span class="hljs-keyword">else</span>
{
    Console.WriteLine(<span class="hljs-string">$"\"Gavin Lon\" was found at position <span class="hljs-subst">{indx}</span>"</span>);
}
<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// "freeCodeCamp" was found at position 46 in the narrative</span>
<span class="hljs-comment">// "Gavin Lon" was found at position 0</span>
</code></pre>
<h3 id="heading-the-replace-built-in-method">The Replace Built-in Method</h3>
<p>Another example of common string related functionality used in C# is finding a specific literal string value within text stored in a variable and replacing the relevant literal string with another literal string value. You can do this in C# using the builtin <code>Replace</code> method.</p>
<p>Check out the code example showing this in figure 19.</p>
<p>Figure 19.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> narrative = <span class="hljs-string">"Gavin Lon loves to create free courses on the freeCodeCamp YouTube channel."</span>;
<span class="hljs-keyword">var</span> newNarrative = narrative.Replace(<span class="hljs-string">"Gavin Lon"</span>, <span class="hljs-string">"Farhan Hassan Chowdury"</span>);
Console.WriteLine(newNarrative);
<span class="hljs-comment">// Output: Farhan Hassan Chowdury loves to create free courses on the freeCodeCamp YouTube channel.</span>
</code></pre>
<h3 id="heading-the-substring-built-in-method">The Substring Built-in Method</h3>
<p>Another common example is assigning a portion of text stored within a variable to another variable using the builtin <code>Substring</code> method. Here's a code example depicting this in figure 20.</p>
<p>Figure 20.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> narrative = <span class="hljs-string">"Gavin Lon loves to create free courses on the freeCodeCamp YouTube channel."</span>;
<span class="hljs-keyword">var</span> charityName = narrative.Substring(<span class="hljs-number">46</span>, <span class="hljs-number">12</span>);
Console.WriteLine(charityName);
<span class="hljs-comment">// Output: freeCodeCamp</span>
</code></pre>
<p>You can also watch the YouTube video below for more information and code examples that talk about using and manipulating strings in C#.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/tzJjrrOe69c" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-c-data-type-conversion">C# Data Type Conversion</h2>
<p>As we discussed above, in C#, variables are statically typed at compile time. This means that once a variable has been defined as a specific type, you can’t define the variable again and you can’t assign a value of an incompatible data type to a variable.</p>
<p>Have a look at the example depicted in figure 21 that highlights static typing in C#.</p>
<p>Figure 21.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span> narrative = <span class="hljs-string">"The cat sat on the mat."</span>;
narrative = <span class="hljs-number">1</span> + <span class="hljs-number">1</span>; <span class="hljs-comment">// Compile time error: "Cannot implicitly convert type 'int' to 'string'"</span>
</code></pre>
<p>Here's an example of what happens if you attempt to define a variable twice in code:</p>
<p>Figure 22.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span> a = <span class="hljs-number">1</span>;
<span class="hljs-keyword">string</span> a = <span class="hljs-string">"one"</span>;
<span class="hljs-comment">// The compiler would immediately flag an error and underline the ‘a’ variable, where an attempt to</span>
<span class="hljs-comment">// define variable, a, as string is made.</span>
<span class="hljs-comment">// A compile time error occurs: "A local variable or function named 'a' is already defined in this scope"</span>
</code></pre>
<h3 id="heading-implicit-vs-explicit-data-type-conversion">Implicit vs Explicit Data Type Conversion</h3>
<p>Variables defined as numeric datatypes can be implicitly converted to certain other numeric datatypes – but in other cases an explicit conversion is required.</p>
<p>Implicit data type conversion means that the compiler will automatically convert a variable defined as one data type to another data type, and you don't need to appropriately implement explicit data type conversion code in order for the appropriate data type conversion to occur.</p>
<p>The following code example in figure 23 demonstrates trying to implicitly convert a variable defined as a short integer to the byte data type. Note the commented lines that explain what happens in your code editor.</p>
<p>Figure 23.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">short</span> b = <span class="hljs-number">255</span>;
<span class="hljs-keyword">byte</span> a = b;
<span class="hljs-comment">// The compiler would immediately flag an exception and a red squiggly line would appear under</span>
<span class="hljs-comment">// variable b in the second line of code.</span>
<span class="hljs-comment">// If you hover your mouse pointer over the red squiggly line the following error message is</span>
<span class="hljs-comment">// presented: “Cannot implicitly convert type ‘short’ to ‘byte’. An explicit conversion exists (are you missing a cast?)”</span>
</code></pre>
<p>After reading the commented lines in figure 23, you can see that an explicit conversion is required to satisfy the C# compiler.</p>
<p>The code in figure 24 shows how you can use an explicit type conversion in this case to prevent the relevant data type compile time exception from being flagged.</p>
<p>Figure 24.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">short</span> b = <span class="hljs-number">255</span>;
<span class="hljs-keyword">byte</span> a = Convert.ToByte(b);
Console.Write(b);
<span class="hljs-comment">// When this code runs, 255, is printed to the console screen</span>
</code></pre>
<p>It's important to note that an explicit type conversion can result in a runtime error occurring. If you assigned <code>b</code> with a value of <code>256</code> instead of <code>255</code> (as in the code depicted in figure 24), a run time error would occur when the code is run.</p>
<p>So this explicit type conversion is dangerous because, in this case, the erroneous code would not be flagged at compile time – which would have forced you to fix the error at compile time (before the code is released into production). So this code would result in a runtime error occuring.</p>
<p>The error is caused because the byte data type supports storing whole number values in memory from <code>0</code> to <code>255</code>. A value of <code>256</code> is clearly outside of this range, so a runtime error will occur with the following error message, <code>System.OverFlowException: Value was either too large or too small for an unsigned byte.</code>. So a value of <code>256</code> must be stored in a variable defined with a data type that supports a range that is greater than the range supported by the byte data type.</p>
<p>The next data type in C# that supports a greater range than the byte data type for whole number values is the short integer data type (or short data type). The value range that a short data type supports is from <code>-32,768</code> to <code>32,767</code>.</p>
<p>The variable defined as the short data type would be clearly be appropriate for storing a whole number value of <code>256</code>.</p>
<p>The next data type that supports a greater value range for whole numbers (than the short data type) is the int data type. The int data type supports a value range from <code>-2,147,483,648</code> to <code>2,147,483,647</code>.</p>
<p>The data type that supports the greatest value range for whole numbers is the long data type, which supports values from <code>-9,223,372,036,854,775,808</code> to <code>9,223,372,036,854,775,807</code>.</p>
<p>As we have just discussed, the C# language has data types like the byte data type, the short data type, the int data type and the long datatype for defining variables for the purpose of storing whole number values.</p>
<p>In C#, there are built-in data types appropriate for the storage of values that contain fractal values. Three data types that you can use for the definition of variables for the storage of values with fractal parts are the float, double, and decimal data type.</p>
<p>A great example of a type of value where you’d want to use one of these data types to define a variable (for storing a value that contains a fractal part) is the decimal data type used for storing monetary values. You could use the float or the double data type for storing monetary values, but the decimal data type is more appropriate for this scenario. This is because the decimal data type (although supports less magnitude than the float or double data types) supports greater precision.</p>
<p>In a banking application, for example, where monetary value precision is of the utmost importance, accounting for fractions of value is essential. So the decimal data type (that supports the highest precision for values in C#) should be leveraged for storing monetary values.</p>
<p>Keep in mind that data can be lost when converting a value stored in a variable defined as one particular data type to another data type.</p>
<p>For example, if you have a monetary value stored in a variable defined as a decimal data type that contains a fractal part, converting this value to, for e.g. an int data type would result in the loss of the fractal part of the value.</p>
<p>Here's an example of this depicted in figure 25.</p>
<p>Figure 25</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> monetaryValue = <span class="hljs-number">10.34</span>m; <span class="hljs-comment">// note if the ‘m’ suffix is not provided the data type is</span>

<span class="hljs-comment">// assumed to be the double data type.</span>
<span class="hljs-comment">// The ‘m’ suffix explicitly defines the variable as</span>
<span class="hljs-comment">// decimal</span>
<span class="hljs-keyword">var</span> <span class="hljs-keyword">value</span> = Decimal.ToInt32(monetaryValue); <span class="hljs-comment">//converts decimal to int</span>
Console.WriteLine(<span class="hljs-keyword">value</span>); <span class="hljs-comment">// this outputs 10 – the value of 0.34 is lost</span>
</code></pre>
<p>So you can see that a value of <code>0.34</code> would be lost as a result of running the data type conversion code depicted in figure 25.</p>
<p>You can check out the YouTube video below for more information on implicit and explicit data type conversions in C#.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/NF4lyA1yx8Y" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-c-operators">C# Operators</h2>
<p>C# operators are made up of one or more symbols that signify to the C# compiler that a particular operation should be performed between relevant operands.</p>
<p>In figure 26, we have a few simple examples of built-in C# operators used to perform mathematical operations.</p>
<p>Figure 26.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> a = <span class="hljs-number">1</span>;
<span class="hljs-keyword">var</span> b = <span class="hljs-number">2</span>;
<span class="hljs-keyword">var</span> r = a + b; <span class="hljs-comment">// the ‘+’ symbol signifies to the compiler to perform an appropriate Addition operation</span>
Console.WriteLine(r); <span class="hljs-comment">// prints 3 to the screen</span>
r = a * <span class="hljs-number">2</span>; <span class="hljs-comment">//the ‘*’ symbol signifies to the compiler to perform an appropriate multiplication operation</span>
Console.WriteLine(r); <span class="hljs-comment">//prints 2 to the screen</span>
r = b - a; <span class="hljs-comment">//the ‘-’ symbol signifies to the compiler to perform an appropriate subtraction operation</span>
Console.WriteLine(r); <span class="hljs-comment">// prints 1 to the screen</span>
r = b / <span class="hljs-number">2</span>; <span class="hljs-comment">//the ‘/’ symbol signifies to the compiler to perform an appropriate multiplication operation</span>
Console.WriteLine(r); <span class="hljs-comment">// prints 1 to the screen</span>
</code></pre>
<p>Typically you are able to overload the default behaviour for built-in operators for numeric data types in C#. So you can change the behaviour of specific operators between two operands defined as specific built-in C# data types.</p>
<p>In the above example, the <code>+</code> operator performs an addition mathematical operation between the relevant operands. You could write code to overload the <code>+</code> operator and change the default addition functionality between two integers.</p>
<p>For example, instead of performing an addition operation between <code>1</code> and <code>2</code> where a value of <code>3</code> is the result of the relevant operation, your operator overload code could return <code>12</code>. So in this case the <code>1</code> and <code>2</code> are simply put together as if a concatenation of two string values was being performed. An integer value of <code>12</code> would be the result of the relevant operation.</p>
<p>Of course, overloading the operator in this way may not be very practical. This example merely illustrates how you could change the behaviour of the <code>+</code> operator between two integer values by overloading the <code>+</code> operator in C#.</p>
<h3 id="heading-types-of-c-operators">Types of C# Operators</h3>
<p>The table below is copied from the Microsoft Learn platform at this URL, <a target="_blank" href="https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators">https://learn.microsoft.com/en-us/dotnet/csharp/language-reference/operators</a></p>
<table>
<thead>
<tr>
<th>Operators</th>
<th>Category or name</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="member-access-operators#member-access-expression-">x.y</a>, <a href="member-access-operators#invocation-expression-">f(x)</a>, <a href="member-access-operators#indexer-operator-">a[i]</a>, <a href="member-access-operators#null-conditional-operators--and-"><code>x?.y</code></a>, <a href="member-access-operators#null-conditional-operators--and-"><code>x?[y]</code></a>, <a href="arithmetic-operators#increment-operator-">x++</a>, <a href="arithmetic-operators#decrement-operator---">x--</a>, <a href="null-forgiving">x!</a>, <a href="new-operator">new</a>, <a href="type-testing-and-cast#typeof-operator">typeof</a>, <a href="../statements/checked-and-unchecked">checked</a>, <a href="../statements/checked-and-unchecked">unchecked</a>, <a href="default">default</a>, <a href="nameof">nameof</a>, <a href="delegate-operator">delegate</a>, <a href="sizeof">sizeof</a>, <a href="stackalloc">stackalloc</a>, <a href="pointer-related-operators#pointer-member-access-operator--">x-&gt;y</a></td>
<td>Primary</td>
</tr>
<tr>
<td><a href="arithmetic-operators#unary-plus-and-minus-operators">+x</a>, <a href="arithmetic-operators#unary-plus-and-minus-operators">-x</a>, <a href="boolean-logical-operators#logical-negation-operator-">!x</a>, <a href="bitwise-and-shift-operators#bitwise-complement-operator-">~x</a>, <a href="arithmetic-operators#increment-operator-">++x</a>, <a href="arithmetic-operators#decrement-operator---">--x</a>, <a href="member-access-operators#index-from-end-operator-">^x</a>, <a href="type-testing-and-cast#cast-expression">(T)x</a>, <a href="await">await</a>, <a href="pointer-related-operators#address-of-operator-">&amp;x</a>, <a href="pointer-related-operators#pointer-indirection-operator-"><em>x</em></a>, <a href="true-false-operators">true and false</a></td>
<td>Unary</td>
</tr>
<tr>
<td><a href="member-access-operators#range-operator-">x..y</a></td>
<td>Range</td>
</tr>
<tr>
<td><a href="switch-expression">switch</a>, <a href="with-expression">with</a></td>
<td><code>switch</code> and <code>with</code> expressions</td>
</tr>
<tr>
<td><a href="arithmetic-operators#multiplication-operator-">x  y</a>, <a href="arithmetic-operators#division-operator-">x / y</a>, <a href="arithmetic-operators#remainder-operator-">x % y</a></td>
<td>Multiplicative</td>
</tr>
<tr>
<td><a href="arithmetic-operators#addition-operator-">x + y</a>, <a href="arithmetic-operators#subtraction-operator--">x – y</a></td>
<td>Additive</td>
</tr>
<tr>
<td><a href="bitwise-and-shift-operators#left-shift-operator-">x &lt;&lt;  y</a>, <a href="bitwise-and-shift-operators#right-shift-operator-">x &gt;&gt; y</a>, <a href="bitwise-and-shift-operators#unsigned-right-shift-operator-">x &gt;&gt;&gt; y</a></td>
<td>Shift</td>
</tr>
<tr>
<td><a href="comparison-operators#less-than-operator-">x &lt; y</a>, <a href="comparison-operators#greater-than-operator-">x &gt; y</a>, <a href="comparison-operators#less-than-or-equal-operator-">x &lt;= y</a>, <a href="comparison-operators#greater-than-or-equal-operator-">x &gt;= y</a>, <a href="type-testing-and-cast#is-operator">is</a>, <a href="type-testing-and-cast#as-operator">as</a></td>
<td>Relational and type-testing</td>
</tr>
<tr>
<td><a href="equality-operators#equality-operator-">x == y</a>, <a href="equality-operators#inequality-operator-">x != y</a></td>
<td>Equality</td>
</tr>
<tr>
<td><code>x &amp; y</code></td>
<td><a href="boolean-logical-operators#logical-and-operator-">Boolean logical AND</a> or <a href="bitwise-and-shift-operators#logical-and-operator-">bitwise logical AND</a></td>
</tr>
<tr>
<td><code>x ^ y</code></td>
<td><a href="boolean-logical-operators#logical-exclusive-or-operator-">Boolean logical XOR</a> or <a href="bitwise-and-shift-operators#logical-exclusive-or-operator-">bitwise logical XOR</a></td>
</tr>
<tr>
<td><code>x | y</code></td>
<td><a href="boolean-logical-operators#logical-or-operator-">Boolean logical OR</a> or <a href="bitwise-and-shift-operators#logical-or-operator-">bitwise logical OR</a></td>
</tr>
<tr>
<td><a href="boolean-logical-operators#conditional-logical-and-operator-">x &amp;&amp; y</a></td>
<td>Conditional AND</td>
</tr>
<tr>
<td><a href="boolean-logical-operators#conditional-logical-or-operator-">x || y</a></td>
<td>Conditional OR</td>
</tr>
<tr>
<td><a href="null-coalescing-operator">x ?? y</a></td>
<td>Null-coalescing operator</td>
</tr>
<tr>
<td><a href="conditional-operator">c ? t : f</a></td>
<td>Conditional operator</td>
</tr>
<tr>
<td><a href="assignment-operator">x = y</a>, <a href="arithmetic-operators#compound-assignment">x += y</a>, <a href="arithmetic-operators#compound-assignment">x -= y</a>, <a href="arithmetic-operators#compound-assignment">x *= y</a>, <a href="arithmetic-operators#compound-assignment">x /= y</a>, <a href="arithmetic-operators#compound-assignment">x %= y</a>, <a href="boolean-logical-operators#compound-assignment">x &amp;= y</a>, <a href="boolean-logical-operators#compound-assignment">x |= y</a>, <a href="boolean-logical-operators#compound-assignment">x ^= y</a>, <a href="bitwise-and-shift-operators#compound-assignment">x &lt;&lt;= y</a>, <a href="bitwise-and-shift-operators#compound-assignment">x &gt;&gt;= y</a>, <a href="bitwise-and-shift-operators#compound-assignment">x &gt;&gt;&gt;= y</a>, <a href="null-coalescing-operator">x ??= y</a>, <a href="lambda-operator">=&gt;</a></td>
<td>Assignment and lambda declaration</td>
</tr>
</tbody>
</table>


<p>For more information on C# Operators, you can watch the YouTube Video below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/qGgwm95FK5M" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>For instructions on how you can overload operators in C#, check out the following YouTube video:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/tq3_8GQxM14" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-constants-and-read-only-variables">Constants and Read-only Variables</h2>
<h3 id="heading-introduction-to-constants">Introduction to Constants</h3>
<p>A constant is like a variable in the sense that you can store a value in it by declaring it and assigning it a value. You can then reference that value with a human readable name that denotes the const value in code.</p>
<p>A constant is different from a variable in the sense that it must be assigned a value on the same line in which it is declared. Also, once you have assigned a value to a constant, you cannot assign a new value to that constant at any other point in the code.</p>
<p>You should use constants in your code where they make your code more readable and maintainable. When you appropriately use a const, you don’t have to repeat a value that you assigned to the const in your code. When you need to reference that value in code, you can instead include the human readable name you gave the const in your code that denotes the relevant constant value.</p>
<p>If a const value needs to change, you only need to change the code in one place (that is where the const has been declared). This change will automatically propagate to where the constant is referenced in other lines of code (that are appropriately scoped).</p>
<h3 id="heading-introduction-to-read-only-variables">Introduction to Read-only Variables</h3>
<p>A read-only variable is like a variable in that you can store a value in it by declaring it and assigning it a value. You can then reference that value with a human readable name that denotes the read-only variable.</p>
<p>A read-only variable is different from a variable in that its value can only be changed once in code after it has been declared. Its value can be changed in the constructor of a class, but cannot be changed in other parts of your code.</p>
<p>So if you have assigned a read-only variable with a value in the line where it's declared, you can assign that read-only variable with a different value in the constructor of a class – but you can't then assign that read-only variable a new value in any other code.</p>
<p>So a read-only variable is often referred to as a runtime constant. A constant is declared and assigned its value on the same line of code at compile time, and the value for that const cannot be subsequently changed at compile time (and so also can’t be changed at runtime).</p>
<p>A read-only variable is assigned the value that cannot be subsequently changed at runtime. So with a read-only variable, where it is assigned a value within the constructor of a class, is set once when an object instance is created from that class at runtime. That read-only variable cannot be changed after this assignment is made.</p>
<h3 id="heading-code-example-using-a-const">Code Example Using a Const</h3>
<p>Here's an example of how to use a const depicted in figure 27.</p>
<p>Figure 27.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">const</span> <span class="hljs-keyword">int</span> SpeedOfLight = <span class="hljs-number">299792458</span>;
Console.WriteLine(<span class="hljs-string">$"The speed of light is <span class="hljs-subst">{SpeedOfLight}</span>"</span>);
<span class="hljs-comment">// The output for this code is:</span>
<span class="hljs-comment">// The speed of light is 299792458</span>
</code></pre>
<h3 id="heading-code-example-using-a-read-only-variable">Code Example Using a Read-only Variable</h3>
<p>And here's an example in figure 28 of how to use a read-only variable:</p>
<p>Figure 28.</p>
<pre><code class="lang-csharp">Employee employee = <span class="hljs-keyword">new</span> Employee(<span class="hljs-string">"Admin"</span>);
employee.PrintEmployeeRole();
</code></pre>
<p>Notice how the read-only string variable named <code>"RoleName"</code> has been assigned a value twice. It's assigned an empty string when it's first declared at the top of the class. The read-only variable is assigned its final value within the constructor of the <code>Employee</code> class.</p>
<p>Note that you can only change the value of a read-only variable once, and you can only do this within the constructor of a class. Once a read-only variable’s value is assigned within the constructor of a class, you can't change its value in any other part of the code.</p>
<p>In the example below in figure 29, a method named <code>SetRoleName</code> contains code to change the value of the <code>RoleName</code> read-only variable. This is not possible in C#, because the read-only variable can only be assigned its final value within the contructor of a class. You cannot for e.g. assign the read-only variable a value within a method.</p>
<p>This code will result in a compile time error being flagged by the C# compiler. The error message will state the following in your code editor: <code>A readonly field cannot be assigned to (except in a constructor or init-only setter of the type in which the field is defined or a variable initialiser)</code>.</p>
<h3 id="heading-code-example-of-the-incorrect-use-of-a-read-only-variable">Code Example of the Incorrect Use of a Read-only Variable</h3>
<p>Figure 29.</p>
<pre><code class="lang-csharp">Employee employee = <span class="hljs-keyword">new</span> Employee(<span class="hljs-string">"Admin"</span>);
employee.PrintEmployeeRole();
</code></pre>
<p>For more information on const and read-only variables, you can watch the YouTube video below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/yvOdN5PBY2g" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-c-if-else-if-else-statements">C# if / else if / else Statements</h2>
<h3 id="heading-basic-ifelse-conditional-logic">Basic if/else Conditional Logic</h3>
<p>If statements allow you to include conditional logic in your code. Let's look at a basic example to see how they work.</p>
<p>Let's say you are working on a shopping cart application and a particular piece of code adds a product to the user's shopping cart. In your code, you only want that item added to the user’s shopping cart if the product is in stock.</p>
<p>When a user tries to add a product that is out of stock, you want a message displayed informing the user that the item they want to add is not in stock. You could also add to this message that they should try to add this item to their shopping cart in a week (i.e. when the item may be in stock).</p>
<p>In C#, to automate this conditional logic, you can implement an <code>if / else</code> statement. The code in figure 30 shows how this might look:</p>
<pre><code class="lang-csharp">Product product = <span class="hljs-keyword">new</span>();
product.Name = <span class="hljs-string">"Ladder"</span>;
product.ItemCount = <span class="hljs-number">10</span>;
<span class="hljs-keyword">if</span> (product.ItemCount == <span class="hljs-number">0</span>)
{
    DisplayMessage(<span class="hljs-string">$"<span class="hljs-subst">{product.Name}</span> is currently not in stock. Please try again in a week."</span>);
}
<span class="hljs-keyword">else</span>
{
    AddToShopingCart(product);
    DisplayMessage(<span class="hljs-string">$"A <span class="hljs-subst">{product.Name}</span> has been successfully added to your shopping cart."</span>);
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">DisplayMessage</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> message</span>)</span>
{
    Console.WriteLine(message);
}
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">AddToShopingCart</span>(<span class="hljs-params">Product product</span>)</span>
{
    Console.WriteLine(<span class="hljs-string">"Code runs to add product"</span>);
}

<span class="hljs-keyword">class</span> <span class="hljs-title">Product</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> Name { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; } = <span class="hljs-string">""</span>;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> ItemCount { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}
</code></pre>
<p>The <code>if</code> statement contains a boolean expression. A boolean expression returns either <code>true</code> or <code>false</code>. If the product is in stock, this boolean expression, <code>product.ItemCount == 0</code>, will return <code>false</code>. If the product is not in stock, then the boolean expression will return <code>true</code>.</p>
<p>The <code>if</code> statement expression evaluates whether the relevant product is currently in stock. If the relevant product is no longer in stock, the <code>ItemCount</code> property will return <code>0</code>. In the case, where the number of products in stock is equal to <code>0</code>, code runs and tells the user that the product is not in stock and that they should try to add the product to their cart in a week.</p>
<p>If, however, the count of stock for the product is not equal to <code>0</code> (meaning the product is in stock), code will run that adds the product to the user's shopping cart. A message will also appear on the user's screen stating that the product has been successfully added to the user's shopping cart.</p>
<p>You can simply include an <code>if</code> statement on its own – and not include an <code>else</code> block within the relevant conditional logic. For example, let's say you wanted to output a message to people using a banking application. When their account is overdrawn (that is, they've taken out too much money), the code might look like the basic example in figure 31:</p>
<p>Figure 31.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">decimal</span> currentAccountValue = <span class="hljs-number">1000</span>m;
<span class="hljs-keyword">decimal</span> withdrawalAmount = <span class="hljs-number">2000</span>m;
<span class="hljs-keyword">var</span> balance = currentAccountValue - withdrawalAmount;
<span class="hljs-keyword">if</span> (balance &lt; <span class="hljs-number">0</span>)
{
    DisplayMessage(<span class="hljs-string">"Your account is overdrawn."</span>); <span class="hljs-comment">// this message will be displayed to the user</span>
}
</code></pre>
<h3 id="heading-implementing-ifelse-ifelse-conditional-logic">Implementing if/else if/else Conditional Logic</h3>
<p>Let’s say that in addition to the above code logic, we want to add a requirement so that a specific message is displayed to the person if they can successfully make a withdrawal without their account being overdrawn.</p>
<p>In this requirement, we also want to include a message that gets displayed if their withdrawal results in the balance being less than <code>100</code> dollars.</p>
<p>To account for these additional requirements, we can update the relevant conditional logic with an <code>else if</code> block and an <code>else</code> block. The code in figure 32 shows how this code might look.</p>
<p>Figure 32.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">decimal</span> currentAccountValue = <span class="hljs-number">1000</span>m;
<span class="hljs-keyword">decimal</span> withdrawalAmount = <span class="hljs-number">876</span>m;
<span class="hljs-keyword">var</span> balance = currentAccountValue - withdrawalAmount;
<span class="hljs-keyword">if</span> (balance &lt; <span class="hljs-number">0</span>)
{
    DisplayMessage(<span class="hljs-string">"Your account is overdrawn."</span>);
}
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (balance &lt; <span class="hljs-number">100</span>)
{
    DisplayMessage(<span class="hljs-string">"You have less than 100 dollars left in your account."</span>);
}
<span class="hljs-keyword">else</span>
{
    DisplayMessage(<span class="hljs-string">$"You have successfully withdrawn <span class="hljs-subst">{withdrawalAmount}</span> dollars"</span>);
}
</code></pre>
<p>So how does the <code>if/else if/ else</code> code work? The first boolean expression is evaluated which accounts for if the balance is less than <code>0</code>. If this expression returns <code>true</code>, the message, <code>"Your account is overdrawn."</code>, is displayed to the user.</p>
<p>If that expression returns <code>false</code>, the code in the <code>else if</code> block is evaluated, and then the expression is evaluated to check if the balance is less than <code>100</code>. If this expression returns <code>true</code> (that is, if the value of <code>balance</code> is less than <code>100</code>) the message , <code>"You have less than 100 dollars left in your account."</code>&gt;, is displayed to the user.</p>
<p>If however, the expression returns <code>false</code>, this means that the code within the <code>else</code> block is executed. So the message, <code>"You have successfully withdrawn {withdrawalAmount} dollars"</code> is displayed to the screen.</p>
<p>Each expression is evaluated from top to bottom and each section of the <code>if/else if/else</code> code is mutually exclusive. This means that only one of the statements within each of the sections of the <code>if/else if/else</code> logic can be run when the relevant conditional logic is executed.</p>
<p>When this conditional logic is run, only one of the messages will be displayed to the user as a result of them making a withdrawal from their account.</p>
<h3 id="heading-nested-if-statements">Nested if Statements</h3>
<p>You can also include nested if statements within your conditional logic. An example of this is depicted in figure 33.</p>
<p>Figure 33.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">decimal</span> currentAccountValue = <span class="hljs-number">1000</span>m;
<span class="hljs-keyword">decimal</span> withdrawalAmount = <span class="hljs-number">6500</span>m;
<span class="hljs-keyword">var</span> balance = currentAccountValue - withdrawalAmount;
<span class="hljs-keyword">if</span> (balance &lt; <span class="hljs-number">0</span>)
{
    <span class="hljs-keyword">if</span> (balance &lt; <span class="hljs-number">-5000</span>)
    {
        DisplayMessage(
            <span class="hljs-string">"You have reached your allowable overdraft limit. You will be charged a penalty amount!"</span>
        );
    }
    <span class="hljs-keyword">else</span>
    {
        DisplayMessage(<span class="hljs-string">"Your account is overdrawn."</span>);
    }
}
<span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (balance &lt; <span class="hljs-number">100</span>)
{
    DisplayMessage(<span class="hljs-string">"You have less than 100 dollars left in your account."</span>);
}
<span class="hljs-keyword">else</span>
{
    DisplayMessage(<span class="hljs-string">$"You have successfully withdrawn <span class="hljs-subst">{withdrawalAmount}</span> dollars"</span>);
}
</code></pre>
<p>In the above example, the top <code>if</code> statement first checks to see if the account has been overdrawn. If the account has been overdrawn (that is, the value of <code>balance</code> is less than <code>0</code>), a nested <code>if/else</code> statement runs. A nested <code>if</code> statement is an <code>if</code> statement that resides within another <code>if</code> statement.</p>
<p>The nested <code>if</code> statement only runs if the expression in the <code>if</code>statement in which the nested <code>if</code> statement resides returns <code>true</code>.</p>
<p>The nested <code>if</code> statement depicted in figure 33 further evaluates if the balance is less than <code>-5000</code>. If this expression returns <code>true</code>, then the user sees a message informing them that the amount just drawn from their account has resulted in the account being overdrawn (i.e. in excess of their allowable overdraft amount). It also lets the user know that the user will be charged an additional penalty amount.</p>
<p>The code in the <code>else</code> part of the nested <code>if</code> statement runs if the user’s balance is between <code>-5000</code> and <code>0</code>. This means their account is overdrawn but will not, in this case, result in a penalty amount being charged (because it's within their allowable overdraft limit).</p>
<h3 id="heading-more-complex-conditional-expressions">More Complex Conditional Expressions</h3>
<h4 id="heading-the-ampamp-operator">The &amp;&amp; Operator</h4>
<p>An <code>if</code> statement can include more complex boolean logic as well. For example, you can use the <code>&amp;&amp;</code> operator or the <code>||</code> operator to evaluate multiple boolean expressions on one line. Figure 34 below depicts a code example of using the <code>&amp;&amp;</code> operator in an <code>if</code> statement to evaluate more than one boolean expression on one line.</p>
<p>The <code>&amp;&amp;</code> operator can be translated as "And also". If the first expression on the left side of the <code>&amp;&amp;</code> operator is evaluated as <code>false</code>, this means that the entire boolean expression evaluated by the <code>if</code> statement is deemed <code>false</code>. The boolean expression on the right side of the expression is not evaluated.</p>
<p>In this case, <code>false</code> is returned by the <code>if</code> statement, meaning that the code within the <code>if</code> statements will not be run.</p>
<p>But if, in this example, the condition on the left hand side of the <code>&amp;&amp;</code> operator is <code>true</code>, this means that the expression on the right side of the <code>&amp;&amp;</code> operator must be evaluated. So in this case, if the value of <code>balance</code> is less than <code>-5000</code>, the boolean expression returns <code>false</code>. This means that the entire boolean expression <code>(balance &lt; -4000 &amp;&amp; balance &gt;= -5000)</code> is <code>false</code>. This also means that the message displayed by the code within the <code>if</code> statement will not run.</p>
<p>But if the code on the right side of the <code>&amp;&amp;</code> operator is <code>true</code> (so in this case the balance is greater than or equal to <code>-5000</code>), the entire boolean expression in the <code>if</code> statement is <code>true</code>. This means the message in the <code>if</code> statement will be outputted to the screen. So <code>Your transaction is successful but you are close to your overdraft limit</code> will be outputted to the screen.</p>
<p>Figure 34.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">decimal</span> currentAccountValue = <span class="hljs-number">1000</span>m;
<span class="hljs-keyword">decimal</span> withdrawalAmount = <span class="hljs-number">5500</span>m;
<span class="hljs-keyword">var</span> balance = currentAccountValue - withdrawalAmount;
</code></pre>
<h4 id="heading-the-operator">The || Operator</h4>
<p>You can also use the <code>||</code> operator (as shown in figure 35) when appropriate for boolean expressions that consist of more than one boolean expression.</p>
<p>The <code>||</code> operator can be translated as "or-else". When the boolean expression on the left side of the <code>||</code> operator returns <code>true</code>, the boolean expression on the right side of the <code>||</code> operator does not need to be evaluated. This is because only one of the expressions needs to return true for the entire boolean expression to return <code>true</code>.</p>
<p>If the boolean expression on the left of the <code>||</code> operator returns <code>false</code>, then the expression on the right will be evaluated.</p>
<p>If the expression on the right returns <code>false</code>, then the entire expression returns <code>false</code>. If, however, the expression on the right of the <code>||</code> operator returns <code>true</code>, the entire boolean expression returns <code>true</code>.</p>
<p>Figure 35.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">decimal</span> currentAccountValue = <span class="hljs-number">1000</span>m;
<span class="hljs-keyword">decimal</span> withdrawalAmount = <span class="hljs-number">960</span>m;
<span class="hljs-keyword">var</span> balance = currentAccountValue - withdrawalAmount;
<span class="hljs-keyword">if</span> (withdrawalAmount &lt; <span class="hljs-number">50</span> || balance &lt; <span class="hljs-number">-5000</span>)
{
    RollBackTransaction();
    DisplayMessage(
        <span class="hljs-string">"Your transaction failed either because you tried to withdraw less than 50 dollars or your total withdrawal would have resulted in your account having a balance of less than -5000 dollars which exceeds your overdraft limit."</span>
    );
}
<span class="hljs-keyword">else</span>
{
    DisplayMessage(<span class="hljs-string">"Thank you! Your transaction was successful!"</span>);
    CommitTransaction();
}
</code></pre>
<p>The code in figure 35 evaluates the boolean expression in the <code>if</code> statement as, if the withdrawl amount is less than 50 dollars then rollback the transaction and display the appropriate message. If, however, the withdrawl amount is greater than 50 dollars the expression on the right hand side of the <code>||</code> operator needs to be evaluated because this means that the expression on the left hand side of the <code>||</code> operator has returned <code>false</code>.</p>
<p>So if the expression on the right hand side of the <code>||</code> operator returns <code>true</code> meaning that the customer's <code>balance</code> is less than <code>-5000</code>, the code to rollback the transaction and display the appropriate message must be run.</p>
<p>So the key take away when using the <code>||</code> operator in an <code>if</code> condition is that if one of the expressions on either side of the <code>||</code> operator returns true, this means that the entire condition returns <code>true</code>. In order for the entire condition to return <code>false</code>, both expressions on either side of the <code>||</code> operator must return <code>false</code>.</p>
<p>So if both expressions on either side of the <code>||</code> operator returns <code>false</code>, this means that the customer has made a valid withdrawl, and the customer's transaction proceeds successfully. A message to this effect is displayed to the customer as a result.</p>
<p>Here's a comprehensive explanation of using <code>if</code> statements for conditional logic in C# in the YouTube video below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/2mChNV9GmpM" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-c-loops">C# Loops</h2>
<h3 id="heading-the-for-loop">The for Loop</h3>
<p>Through the use of loops in code, programmers are able to drastically reduce the lines of code required to perform specific tasks. A very simple example of this is displaying a count from <code>1</code> to <code>10</code> where each value is printed on a new line in the console window. Without using a loop the code could look like the code depicted in figure 36.</p>
<p>Figure 36.</p>
<pre><code class="lang-csharp">Console.WriteLine(<span class="hljs-string">"1"</span>);
Console.WriteLine(<span class="hljs-string">"2"</span>);
Console.WriteLine(<span class="hljs-string">"3"</span>);
Console.WriteLine(<span class="hljs-string">"4"</span>);
Console.WriteLine(<span class="hljs-string">"5"</span>);
Console.WriteLine(<span class="hljs-string">"6"</span>);
Console.WriteLine(<span class="hljs-string">"7"</span>);
Console.WriteLine(<span class="hljs-string">"8"</span>);
Console.WriteLine(<span class="hljs-string">"9"</span>);
Console.WriteLine(<span class="hljs-string">"10"</span>);
</code></pre>
<p>Using a <code>for</code> loop in C# you could reduce 10 lines of code to 3 lines of code as is depicted in figure 37. You could update the code so that the <code>for</code> loop loops 100 times instead of 10 times. To do this you would change the relevant <code>for</code> loop expression from, <code>count&lt;=10</code>, to <code>count &lt;=100</code>. So in the code example depicted in figure 38 you would have reduced 100 lines of code to 3 lines of code by using the <code>for</code> loop to achieve exactly the same output.</p>
<p>Figure 37.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> count = <span class="hljs-number">1</span>; count &lt;= <span class="hljs-number">10</span>; count++)
{
    Console.WriteLine(count);
}
</code></pre>
<p>Figure 38.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> count = <span class="hljs-number">1</span>; count &lt;= <span class="hljs-number">100</span>; count++)
{
    Console.WriteLine(count);
}
</code></pre>
<p>You could implement the same functionality using a <code>while</code> loop that loops 10 times as is depicted in figure 39.</p>
<h3 id="heading-the-while-loop">The while Loop</h3>
<p>Figure 39.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> count = <span class="hljs-number">1</span>;
</code></pre>
<h3 id="heading-the-do-while-loop">The do-while Loop</h3>
<p>You could implement the same functionality using a <code>do-while</code> loop in C# as is depicted in figure 40.</p>
<p>Figure 40.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> count = <span class="hljs-number">1</span>;
<span class="hljs-keyword">do</span>
{
    Console.WriteLine(count);
    count++;
} <span class="hljs-keyword">while</span> (count &lt;= <span class="hljs-number">10</span>);
</code></pre>
<p>The difference between a <code>while</code> loop and a <code>do-while</code> loop is that a <code>do-while</code> loop will always execute the code within it at least once. With a <code>while</code> loop the boolean conditional expression is at the top of the loop so when this expression returns <code>false</code> (i.e. before code within the <code>while</code> loop has a chance to run), no code within the <code>while</code> loop will run. With the <code>do-while</code> loop, code within the <code>do-while</code> loop is always executed at least once. In the example depicted in Figure 41, the statements within the <code>while</code> block will never run.</p>
<p>Figure 41.</p>
<p>The value of <code>count</code> is equal to <code>11</code> and the boolean conditional expression, <code>(count &lt;= 10)</code>, returns <code>false</code> so the two lines of code within the <code>while</code> loop will not execute. Let's look at a similar example but where a <code>do-while</code> loop is used. This example is depicted in figure 42.</p>
<p>Figure 42.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> count = <span class="hljs-number">11</span>;
<span class="hljs-keyword">do</span>
{
    Console.WriteLine(count);
    count++;
} <span class="hljs-keyword">while</span> (count &lt;= <span class="hljs-number">10</span>);
</code></pre>
<p>The lines of code within the <code>do-while</code> loop will execute one time. So the result of this is the value of <code>11</code> will be printed to the console screen. After the value of <code>11</code> is printed to the console screen, the boolean expression, <code>(count &lt;= 10)</code>, is run. The value of <code>count</code> is <code>11</code> which means the boolean expression at the bottom of the <code>do-while</code> loop returns <code>false</code>, so the loop will be exited.</p>
<h3 id="heading-the-foreach-loop">The foreach Loop</h3>
<p>In C# you can leverage a <code>foreach</code> loop instead of a <code>for</code> loop. One of the advantages of using a <code>foreach</code> loop rather than a <code>for</code> loop is that if the number of traversals that need to occur in order to traverse all of the relevant items in the loop change, the code created for the execution of the loop does not need to change. Consider this example depicted in figure 43 where a <code>foreach</code> loop is used to print each value contained within an array to the console screen.</p>
<p>Figure 43.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span>[] arr = { <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span> };
<span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> val <span class="hljs-keyword">in</span> arr)
{
    Console.Write(<span class="hljs-string">$"<span class="hljs-subst">{val}</span> "</span>);
}
<span class="hljs-comment">// Output:  1 2 3 4 5 6 7 8 9 10</span>
</code></pre>
<p>Consider what happens when the number of items and values in the array are changed. Please see a code example depiciting this in figure 44.</p>
<p>Figure 44.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span>[] arr = { <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">10</span>, <span class="hljs-number">11</span>, <span class="hljs-number">13</span>, <span class="hljs-number">12</span> };
<span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">var</span> val <span class="hljs-keyword">in</span> arr)
{
    Console.Write(<span class="hljs-string">$"<span class="hljs-subst">{val}</span> "</span>);
}
<span class="hljs-comment">// Output:  1 2 3 4 5 6 7 8 9 10 11 13 12</span>
</code></pre>
<p>A <code>for</code> loop used to execute the same code would look like the code example depicted in figure 45.</p>
<p>Figure 45.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span>[] arr = { <span class="hljs-number">10</span>, <span class="hljs-number">8</span>, <span class="hljs-number">5</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">6</span>, <span class="hljs-number">7</span>, <span class="hljs-number">4</span>, <span class="hljs-number">8</span>, <span class="hljs-number">9</span>, <span class="hljs-number">3</span>, <span class="hljs-number">11</span>, <span class="hljs-number">13</span>, <span class="hljs-number">12</span> };
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">var</span> x = <span class="hljs-number">0</span>; x &lt;= arr.Length - <span class="hljs-number">1</span>; x++)
{
    Console.Write(<span class="hljs-string">$"<span class="hljs-subst">{arr[x]}</span> "</span>);
}
<span class="hljs-comment">// Output: 10 8 5 1 2 6 7 4 8 9 3 11 13 12</span>
</code></pre>
<p>With the <code>for</code> loop, the length of the array must be included in the code for executing the loop. The index of the array must be included in the code where each item is printed to the screen. You can accomplish the same task using a <code>for</code> loop and a <code>foreach</code> loop in these scenarios but the <code>foreach</code> loop is cleaner and easier to read. So with the <code>foreach</code> loop you don’t have to worry about the index of the elements in the array or the length of the array.</p>
<p>For more details on loops in C# and more code examples, please watch the YouTube video below this paragraph.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/oO0GXIIE56U" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-c-arrays">C# Arrays</h2>
<p>An array is a data structure. You can store multiple values of the same type within an array. You can also store multiple types within an array by defining the array elements as the object data type.</p>
<p>All types in C# inherit from the object data type, so you can store multiple types of data within an array where the elements are defined as objects.</p>
<p>Consider the below example depicted in figure 46 where an integer array is defined that can store 10 integer values.</p>
<p>Figure 46.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span>[] arrValues = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">10</span>];
</code></pre>
<p>In this example, the array can only store integer values. If you try to store any other type in this array, an appropriate compile time error will be flagged.</p>
<p>In the next example in figure 47, you can only store string values.</p>
<p>Figure 47.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">string</span>[] arrayStringValues = <span class="hljs-keyword">new</span> <span class="hljs-keyword">string</span>[<span class="hljs-number">10</span>];
</code></pre>
<p>But in the example depicted in figure 48 below, you can store both string and integer values as well as other types of data in the array. This is because, as discussed, all data types in C# inherit from the object data type. So in the array in the example below, you can store string values, integer values, decimal values, boolean values, char values, user defined typed values, and so on.</p>
<p>Figure 48.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">object</span>[] arrayObjectValues = <span class="hljs-keyword">new</span> <span class="hljs-keyword">object</span>[<span class="hljs-number">10</span>];
</code></pre>
<p>Storing multiple data types in this way this is known as 'boxing', because, for example, if an integer is stored as an element within an array defined as object, the integer data is first ‘boxed’ within the object type. This means that in order to retrieve the data as its appropriate data type from the array, the value must first be ‘unboxed’. This simply means that the relevant array element is explicitly type cast from an object to its appropriate data type.</p>
<p>It is important to note that when defining an array as an object, you are in effect circumventing the type system of the C# language and losing the benefits of a strongly typed language (like faster performance, as well as increased robustness of runtime code).</p>
<p>The 'unboxing' code that needs to run when retrieving values from the array can potentially cause runtime errors to occur, as well as causes a casting runtime overhead. And this slows down the performance of the code.</p>
<p>So strongly typing the array is recommended to increase runtime performance and runtime robustness. This lets you leverage the benefits of the strong type system supported by the C# language.</p>
<h3 id="heading-one-dimensional-arrays">One-dimensional Arrays</h3>
<p>In C# you have three types of arrays, one dimensional arrays, multi-dimensional arrays, and jagged arrays.</p>
<p>A one dimensional array allows for the storage of data that is one dimensional in nature. An example of this would be an array of grades for a particular student for a particular year.</p>
<p>So for example, let's say that a student received the following grades in 2023: 60, 50, 72, 85, 91. These grades could be stored in a one dimensional integer array like is depicted in figure 49.</p>
<p>Figure 49.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span>[] grades = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">5</span>]{<span class="hljs-number">60</span>, <span class="hljs-number">50</span>, <span class="hljs-number">72</span>, <span class="hljs-number">85</span>, <span class="hljs-number">91</span>};
</code></pre>
<h3 id="heading-multi-dimensional-arrays">Multi-dimensional Arrays</h3>
<h4 id="heading-two-dimensional-arrays">Two-dimensional Arrays</h4>
<p>An example of using a multi-dimensional array could be an array where more than one student’s grades are stored in the array. This code example is depicted in below figure 50.</p>
<p>So lets say that grades for Sarah, John, and Bob are stored within the two dimensional array. Within the main set of curley brackets, all of the values are included in the two dimensional array. Also within the main set of curly brackets are three sets of curly brackets, one set for each student. And within each of the three sets of curly brackets are 5 grades pertaining to the three students.</p>
<p>So lets say the first set of grades belongs to Sarah, the second set of grades belongs to John, and the third set of grades belongs to Bob.</p>
<p>Figure 50.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span>[,] studentGrades = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">3</span>, <span class="hljs-number">5</span>]
{
    { <span class="hljs-number">60</span>, <span class="hljs-number">50</span>, <span class="hljs-number">72</span>, <span class="hljs-number">85</span>, <span class="hljs-number">91</span> },
    { <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">67</span>, <span class="hljs-number">80</span>, <span class="hljs-number">93</span> },
    { <span class="hljs-number">48</span>, <span class="hljs-number">58</span>, <span class="hljs-number">90</span>, <span class="hljs-number">57</span>, <span class="hljs-number">87</span> }
};
</code></pre>
<p>So the first subscript in the array is 3, which in this example represents the number of students. The second subscript in the array represents the number of grades. So you could use a C# nested <code>for</code> loop to loop through the items in this array and print their values to the screen in a two dimensional matrix display.</p>
<p>In figure 51 you'll see an example of looping through a two dimensional array and displaying the results to the console screen in a two dimensional matrix.</p>
<p>Figure 51.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span>[,] studentGrades = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">3</span>, <span class="hljs-number">5</span>]
{
    { <span class="hljs-number">60</span>, <span class="hljs-number">50</span>, <span class="hljs-number">72</span>, <span class="hljs-number">85</span>, <span class="hljs-number">91</span> },
    { <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">67</span>, <span class="hljs-number">80</span>, <span class="hljs-number">93</span> },
    { <span class="hljs-number">48</span>, <span class="hljs-number">58</span>, <span class="hljs-number">90</span>, <span class="hljs-number">57</span>, <span class="hljs-number">87</span> }
};
</code></pre>
<h4 id="heading-three-dimensional-arrays">Three-dimensional Arrays</h4>
<p>You could add another dimension to this array – for example, you could split the grades up for each student so the grades relate to a particular time of year.</p>
<p>For simplicity, let's divide the year in half. So for the first half of 2023, Sarah received the following grades: 54, 42, 70, 80, 93. For the second half of the year, Sarah received the these grades: 65, 46, 68, 90, 95.</p>
<p>So in this example (depicted in figure 52), the relevant three dimensional array includes the results for Sarah and two other students (John and bob) where their results include their grades for the first half of 2023 as well as their grades for the second half of 2023.</p>
<p>Figure 52.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span>[,,] studentGrades = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">3</span>, <span class="hljs-number">2</span>, <span class="hljs-number">5</span>]
{
    {
        { <span class="hljs-number">60</span>, <span class="hljs-number">50</span>, <span class="hljs-number">72</span>, <span class="hljs-number">85</span>, <span class="hljs-number">91</span> },
        { <span class="hljs-number">65</span>, <span class="hljs-number">46</span>, <span class="hljs-number">68</span>, <span class="hljs-number">90</span>, <span class="hljs-number">95</span> }
    },
    {
        { <span class="hljs-number">45</span>, <span class="hljs-number">40</span>, <span class="hljs-number">64</span>, <span class="hljs-number">70</span>, <span class="hljs-number">90</span> },
        { <span class="hljs-number">55</span>, <span class="hljs-number">50</span>, <span class="hljs-number">73</span>, <span class="hljs-number">90</span>, <span class="hljs-number">95</span> }
    },
    {
        { <span class="hljs-number">46</span>, <span class="hljs-number">60</span>, <span class="hljs-number">88</span>, <span class="hljs-number">55</span>, <span class="hljs-number">89</span> },
        { <span class="hljs-number">50</span>, <span class="hljs-number">56</span>, <span class="hljs-number">92</span>, <span class="hljs-number">59</span>, <span class="hljs-number">85</span> }
    }
};
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; studentGrades.GetLength(<span class="hljs-number">0</span>); i++)
{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; studentGrades.GetLength(<span class="hljs-number">1</span>); j++)
    {
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> k = <span class="hljs-number">0</span>; k &lt; studentGrades.GetLength(<span class="hljs-number">2</span>); k++)
        {
            Console.Write(<span class="hljs-string">$"<span class="hljs-subst">{studentGrades[i, j, k]}</span>\t"</span>);
        }
        Console.WriteLine();
    }
    Console.WriteLine();
    Console.WriteLine();
}
</code></pre>
<p>So in figure 52 above, you can see the first student’s data is printed to the console screen where the first line presents the student’s grades for the first half of the year.</p>
<p>This is followed by a line feed and the first student’s grades for the second half of the year are printed on the subsequent line. Two line feeds follow the data printed for the first student. This is followed by the second student’s grades, and so on.</p>
<p>The first dimension of the array is in this case denoted by the three students. The second dimension of the array is in this case denoted by the the parts of the year (in this case the year is divided into 2 parts (or two halves)). The third dimension of the array is denoted by the actual grades for each student (in this case, five grades).</p>
<p>So depicted in Figure 52 is an example of a three dimensional array declared and initialised. The code that follows outputs the values stored in the three dimensional array to the console screen. So the example in figure 52 is a great example of C# code that implements nested for loops to print out the data stored in a 3 dimensional array to the console screen.</p>
<p>So with this example, you are in effect printing out three dimensional data onto a 2 dimensional screen using C#.</p>
<h3 id="heading-jagged-arrays">Jagged Arrays</h3>
<p>Basically a Jagged array is an array of arrays. It allows you to store uneven data (if you like).</p>
<p>So what do I mean by uneven data? If you go back to the 2-dimensional array example depicted in figure 51, you have 5 grades represented for each of the three students.</p>
<p>Let’s say that student number two (John in the example) studies only the first three subjects, so you only have grades for those three subjects for John. But you have five grades pertaining to the first three subjects as well as grades pertaining to the last two subjects for the other two students (Sarah and Bob) completed. You still want to store John’s three grades along with the five grades for Sarah and Bob in the array.</p>
<p>Well, good news - you can store all of the data (without the need to include redundant ‘placeholder’ data for John’s missing two grades) by using a jagged array.</p>
<p>In the example depicted in figure 53, C# code is implemented for storing the relevant grades in a jagged array. The code that follows outputs the grades to the console screen.</p>
<p>Figure 53.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span>[][] studentGrades = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">3</span>][];
studentGrades[<span class="hljs-number">0</span>] = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">5</span>] { <span class="hljs-number">60</span>, <span class="hljs-number">50</span>, <span class="hljs-number">72</span>, <span class="hljs-number">85</span>, <span class="hljs-number">91</span> }; <span class="hljs-comment">// Sarah’s grades</span>
studentGrades[<span class="hljs-number">1</span>] = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">3</span>] { <span class="hljs-number">50</span>, <span class="hljs-number">45</span>, <span class="hljs-number">67</span> }; <span class="hljs-comment">// John’s grades</span>
studentGrades[<span class="hljs-number">2</span>] = <span class="hljs-keyword">new</span> <span class="hljs-keyword">int</span>[<span class="hljs-number">5</span>] { <span class="hljs-number">48</span>, <span class="hljs-number">58</span>, <span class="hljs-number">90</span>, <span class="hljs-number">57</span>, <span class="hljs-number">87</span> }; <span class="hljs-comment">// Bob’s grades</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; studentGrades.Length; i++)
{
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; studentGrades[i].Length; j++)
    {
        Console.Write(<span class="hljs-string">$"<span class="hljs-subst">{studentGrades[i][j]}</span>\t"</span>);
    }
    Console.WriteLine();
}
</code></pre>
<p>You can see by the outputted results, that when compared to the output in the two dimensional array example depicted in figure 51, the shape of the data is jagged (uneven). This is why this data structure is referred to as a jagged array.</p>
<p>You can watch the YouTube video below for more information on arrays in C#, as well as more code examples of how arrays are used in C# code.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/K4wjL7kRJyE" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-c-methods">C# Methods</h2>
<h3 id="heading-introduction-to-methods-in-c">Introduction to Methods in C</h3>
<p>A method is simply a block of code that contains a series of statements. When a program is run and a method is called, the statements within that method are executed.</p>
<p>In C#, every statement is executed in the context of a method. So methods are fundamental to how C# code is structured and executed.</p>
<h3 id="heading-the-main-method">The Main Method</h3>
<p>The <code>Main</code> method is the entry point of all C# applications. So this is the method that is first executed whenever a program coded in C# is run.</p>
<p>The CLR (Common Language Runtime) calls the <code>Main</code> method when a program (coded in C#) is first started. In C# you can create both named methods and anonymous methods. In this part of the C# book, we'll discuss named methods.</p>
<h3 id="heading-the-structure-of-methods">The Structure of Methods</h3>
<p>Methods are used to encapsulate a series of statements that get executed when the method is called in code. In some cases, a method is just a series of statements where (at runtime) the statements are executed in sequence and no value is returned from the relevant method to the calling code.</p>
<p>These methods (that don’t return a value) contain the <code>void</code> keyword in the relevant method declaration to signify that the method does not return a value.</p>
<p>Methods can also be created that contain a list of statements that are executed sequentially. At the end of the list of statements, a value of a specified data type is returned to the calling code.</p>
<p>For methods that return values, the data type denoting the value that must be returned from the method is appropriately included within the method's declaration. At the end of the sequence of statements encapsulated by the method, the <code>return</code> keyword is included, followed by the value that will be returned to the calling code, on the same line as where the <code>return</code> keyword is included.</p>
<p>You can see a simple example of a method that is used for returning the result of a mathematical operation in figure 54.</p>
<p>Figure 54.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span> result = AddTwoNumbers(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>);
Console.WriteLine(result);
<span class="hljs-keyword">int</span> result2 = AddTwoNumbers(<span class="hljs-number">300</span>, <span class="hljs-number">400</span>);
Console.WriteLine(result2);
</code></pre>
<p>In the example above, this simple method has a method declaration that contains a <code>private</code> access modifier. This means that the <code>AddTwoNumbers</code> method is only accessible from methods contained within the same class in which the <code>AddTwoNumbers</code> method resides.</p>
<p>The <code>AddTwoNumbers</code> method returns a value that is of type integer. This is denoted by the <code>int</code> alias used in the method declaration.</p>
<p>The method declaration contains two parameters, both of the integer data type. The first line of code within the method executes the addition mathematical operation between two arguments that are appropriately passed to the method’s parameters at runtime. The second line of code within the method uses the <code>return</code> C# keyword followed by the result of the previous statement, to return the result of the relvant mathematical operation to the calling code.</p>
<p>The <code>return</code> keyword denotes returning a value to the calling code, which in this case will be the result of the mathematical operation executed in the first line of code within the <code>AddTwoNumbers</code> method.</p>
<p>In the example below (depicted in figure 55), two statements are contained within the method. A fundamental difference between the <code>AddTwoNumbers</code> method (depicted in figure 54) and the method below (depicted in Figure 55) is that the <code>LogFormulaResultToFile</code> method (depicted in figure 55) does not return a value. This is denoted by the <code>void</code> keyword which is included within the <code>LogFormulaResultToFile</code> method declaration.</p>
<p>Figure 55.</p>
<pre><code class="lang-csharp">LogFormulaResultToFile(<span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-string">"This is the result: "</span>);

<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// This is the result:  7</span>

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">LogFormulaResultToFile</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> operand1, <span class="hljs-keyword">int</span> operand2, <span class="hljs-keyword">string</span> message</span>)</span>
{
    <span class="hljs-keyword">int</span> result = operand1 + operand2;
    LogToFile(<span class="hljs-string">$"<span class="hljs-subst">{message}</span> <span class="hljs-subst">{result}</span>"</span>);
}

<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">LogToFile</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> message</span>)</span>
{
    Console.WriteLine(message); <span class="hljs-comment">// for simplicity print message to screen rather than write to file</span>
}
</code></pre>
<p>The fundamental structure for every method in C# is defined by its method signature. And we’ve discussed that within methods are a series of statements.</p>
<p>The method signature defines what type of value is returned by the method, the name of the method, and the level of access (or scope) associated with the method (for example, <code>private</code> or <code>public</code>). The method signature also includes zero, one, or a list of parameters denoting arguments that can be passed to the method when the method is called at runtime. The method signature can also contain the following keywords, <code>abstract</code>,<code>sealed</code>, or <code>virtual</code>. These keywords are beyond the scope of this handbook.</p>
<p>Methods are declared in a <code>class</code>, <code>struct</code> or <code>interface</code>. Methods in an <code>interface</code> do not contain any implementation (that is, any statements) and only the method signature is defined in an <code>interface</code>.</p>
<p>Note that methods defined within an <code>interface</code> do not include access modifiers. When a <code>class</code> implements an <code>interface</code>, the methods contained within the <code>interface</code> must be appropriately implemented by the <code>class</code> that implements the <code>interface</code>.</p>
<p>On the other hand, when methods are contained within a <code>class</code> or a <code>struct</code>, both the method signatures and code implementations for the methods are included.</p>
<p>The example below (depicted in figure 56) demonstrates the implementation of a <code>public</code> method that can be used to return the factorial of a number.</p>
<p>Figure 56.</p>
<pre><code class="lang-csharp">MathFunctions mathFunctions = <span class="hljs-keyword">new</span> MathFunctions();
<span class="hljs-keyword">var</span> result = mathFunctions.GetFactorial(<span class="hljs-number">6</span>);
Console.WriteLine(result);

<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// 720</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">MathFunctions</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">GetFactorial</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> num</span>)</span>
    {
        <span class="hljs-keyword">int</span> fact = <span class="hljs-number">1</span>;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= num; i++)
        {
            fact = fact * i;
        }
        <span class="hljs-keyword">return</span> fact;
    }
}
</code></pre>
<p>In the <code>public</code> method named, <code>GetFactorial</code>, a local variable is declared and initialised to a value of <code>1</code> at the top of the method.</p>
<p>A local variable is a variable that has local scope, meaning that in this case the <code>fact</code> variable is not accessible outside of the <code>GetFactorial</code> method. It is only accessible within the <code>GetFactorial</code> method. This means that the <code>fact</code> variable’s value cannot be changed from outside the method but can only be changed from within the method.</p>
<p>You can see that within the <code>for</code> loop, a statement is run that alters the value of the <code>fact</code> variable with each iteration of the loop. Once the the loop is terminated, a final result is reached and that result is returned (using the C# <code>return</code> keyword) to the calling code.</p>
<p>If for example the <code>GetFactorial</code> method resides within a class named, <code>MathFunctions</code>, the calling code could look like the example below depicted in figure 57.</p>
<p>Figure 57.</p>
<pre><code class="lang-csharp">
MathFunctions mathFunctions = <span class="hljs-keyword">new</span> MathFunctions();
<span class="hljs-keyword">var</span> result = mathFunctions.GetFactorial(<span class="hljs-number">6</span>);
Console.WriteLine(result);
</code></pre>
<p>Below, you'll see an example of a <code>private</code> method that uses C# string manipulation to appropriately concatenate and reformat the string arguments representing the first name and last name of an employee (depicted in figure 58).</p>
<p>So if the employee’s first name is "John" and the employee's last name is "Denver", the relevant method will return the string value, "Denver, J". The method concatenates the last name with a comma followed by the a further concatenation of the first initial of the employee’s first name.</p>
<p>This concatenation operation is presented by the <code>return</code> keyword on the same line, which means the result of the concatenation operation is returned to the calling code.</p>
<p>Figure 58.</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> <span class="hljs-title">FormatName</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> firstName, <span class="hljs-keyword">string</span> lastName</span>)</span>
{
    <span class="hljs-keyword">return</span> lastName + <span class="hljs-string">", "</span> + firstName.Substring(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>).ToUpper();
}
</code></pre>
<p>In figure 59 below, we have a code sample where a class named <code>Employee</code> is included. This class contains a read-only property named, <code>DisplayName</code>. This property exposes the formatted <code>name</code> to the calling code through the use of the <code>public</code> access modifier.</p>
<p>The <code>firstName</code> and <code>lastName</code> string arguments are passed to the constructor of the <code>Employee</code> class when it is instantiated by the calling code. The calling code can then write the relevant employee’s formatted name to the console screen. So the <code>private</code> method, <code>FormatName</code>, is not accessible to the calling code. The formatting of the employee's name is handled within the <code>Employee</code> class.</p>
<p>This is a design decision driven by the requirements.</p>
<p>Figure 59.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Employee</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> firstName = <span class="hljs-string">""</span>;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> lastName = <span class="hljs-string">""</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Employee</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> firstName, <span class="hljs-keyword">string</span> lastName</span>)</span>
    {
        <span class="hljs-keyword">this</span>.firstName = firstName;
        <span class="hljs-keyword">this</span>.lastName = lastName;
    }

    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> DisplayName
    {
        <span class="hljs-keyword">get</span> { <span class="hljs-keyword">return</span> FormatName(<span class="hljs-keyword">this</span>.firstName, <span class="hljs-keyword">this</span>.lastName); }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> <span class="hljs-title">FormatName</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> firstName, <span class="hljs-keyword">string</span> lastName</span>)</span>
    {
        <span class="hljs-keyword">return</span> lastName + <span class="hljs-string">", "</span> + firstName.Substring(<span class="hljs-number">0</span>, <span class="hljs-number">1</span>).ToUpper();
    }
}
</code></pre>
<p>The calling code could look like the code example depicted in figure 60:</p>
<p>Figure 60.</p>
<pre><code class="lang-csharp">Employee employee = <span class="hljs-keyword">new</span> Employee(<span class="hljs-string">"John"</span>, <span class="hljs-string">"Denver"</span>);
Console.WriteLine(employee.DisplayName);
<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// Denver, J</span>
</code></pre>
<p>The code example depicted in figure 59 demonstrates the use of the code design concept of encapsulation. The complexity of the <code>FormatName</code> functionality is encapsulated within a <code>private</code> method in the <code>Employee</code> class so the calling code is not concerned with the implementation detail of the formatting functionality of the employee’s name. The calling code only needs to reference the <code>DisplayName</code> property on an object derived from the <code>Employee</code> user defined type (or class). The formatting functionality is handled within the <code>Employee</code> class.</p>
<p>The <code>private</code> access modifier enforces the encapsulation of the formatting functionality. The <code>FormatName</code> method is not accessible from the calling code, but is only accessible from within the <code>Employee</code> class.</p>
<p>This particular design decision is enforced through the use of the <code>private</code> access modifier appropriately contained within the <code>FormatName</code> method declaration.</p>
<h2 id="heading-c-classes">C# Classes</h2>
<p>C# supports object-oriented programming. All data types including user defined types in C# inherit from the <code>object</code> data type, so you could say that everything in C# is an object. So an <code>int</code> is an object, a <code>decimal</code> is an object, a <code>string</code> is an object, a <code>bool</code> is an object etc…</p>
<p>The main difference between an <code>int</code>, <code>decimal</code> and <code>bool</code> when compared to a <code>string</code> data type is that the <code>int</code>, <code>decimal</code> and <code>bool</code> data types inherit from the ValueType abstract class, the ValueType class in turn inserts from the <code>object</code> type. This means that the <code>int</code>, <code>decimal</code> and <code>bool</code> data types are value types. Strings, on the other hand are reference types. The <code>string</code> data type does not inherit from the ValueType abstract class but inherits directly from <code>System.Object</code> class.</p>
<p>Note that <code>int</code>, <code>bool</code> and <code>decimal</code> data types are implemented as structs in C#. Structs are value types and are similar to classes in many ways.</p>
<p>The main difference between a struct and a class in C# is that structs are value types and classes are reference types. The <code>string</code> data type inherits directly form the <code>System.Object</code> type which means the <code>string</code> datatype is a reference type.</p>
<p>In C# you are able to create your own custom classes. When you create a class in C#, behind the scenes your user defined type inherits from the <code>System.Object</code> type. So your user defined class is a reference type.</p>
<p>Note that you can also create user defined structs using the <code>struct</code> keyword, whereas when you create user defined classes, you use the <code>class</code> keyword.</p>
<p>The underlying difference between a class and a struct is the way they are stored in memory. Value types store their data directly in a memory location known as the stack, while reference types store a numeric reference (memory address) on the stack, to an object containing the actual data (where the data is actually stored) known as the heap.</p>
<p>The stack stores data in a more structured way than how data is stored on the heap. Make sure you understand this difference, because it affects how the objects derived from classes or structs are copied and passed around in code, and the efficiency with which data is stored and retreived in memory.</p>
<p>Structs are generally faster than classes, so if you are working with large amounts of data, structs may be a more efficient option because they don’t require the overhead of heap memory. Structs may be the best option when needing to represent a simple data structure that contains  data types like integer, boolean, or decimal datatypes.</p>
<p>Structs also have the benefit of being handled more efficiently in memory, which means when dealing with large amounts of instantiated objects from a particular data structure, a struct may be a better option to represent that data, rather than a class.</p>
<p>Structs and classes are both similar in that they both support concepts like for example constructors, fields, properties and methods.</p>
<p>In figure 61 the <code>Player</code> class is used as a template for an object that represents a game object for a particular game.</p>
<p>Figure 61</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Player</span>
{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">string</span> name = <span class="hljs-string">""</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Player</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> name</span>)</span>
    {
        <span class="hljs-keyword">this</span>.name = name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Move</span>(<span class="hljs-params"><span class="hljs-keyword">double</span> x, <span class="hljs-keyword">double</span> y</span>)</span>
    {
        Console.WriteLine(<span class="hljs-string">$"Moving <span class="hljs-subst">{name}</span> to coordinates where 'x' = <span class="hljs-subst">{x}</span>, and 'y' = <span class="hljs-subst">{y}</span>"</span>);
    }
}
</code></pre>
<p>In the above example (depicted in figure 61), you can see some of the fundamental concepts in C# being expressed, through for example the use of the <code>class</code> keyword, the <code>private</code> and public access modifiers, a constructor that contains one parameter, a method that contains two parameters and a private member variable defined as a string.</p>
<h3 id="heading-the-class-keyword">The class keyword</h3>
<p>The class keyword in C# is used for defining a user defined reference type or class.</p>
<h3 id="heading-the-public-access-modifier">The Public Access Modifier</h3>
<p>Preceding the <code>class</code> keyword is the <code>public</code> access modifier. The use of the <code>public</code> access modifier in this way means that this class can be accessed and instantiated from anywhere within the assembly in which the class resides as well as from outside of the assembly in which the class resides.</p>
<h3 id="heading-the-private-member-variable">The Private Member Variable</h3>
<p>The <code>private</code> member variable named, <code>name</code>, is not directly accessible to code that exists outside of the <code>Player</code> class. The <code>name</code> member variable can only be accessed and used from within a property, constructor or method that resides within the <code>Player</code> class.</p>
<h3 id="heading-the-constructor">The Constructor</h3>
<p>The <code>Player</code> class (depicted in the code example in figure 61) has one constructor. Classes are instantiated into objects at runtime. The Player constructor contains one string parameter named <code>name</code>. When calling code instantiates an object derived from the <code>Player</code> class, the name of the <code>Player</code> can be passed as an argument to the Player objects constructor.</p>
<p>Within the constructor of the ‘Player’ class the private member variable named, <code>name</code> is assigned the value passed in by calling code to the parameterised constructor of the ‘Player’ class. When the calling code subsequently calls the <code>Move</code> method, the <code>name</code> member variable is accessed and utilised by code within the <code>Move</code> method. The constructor is called when the object is derived from the <code>Player</code> class.</p>
<p>The constructor enables the calling code to assign a value for the name of the player pertaining to the relevant object at the point at which the relevant object is instantiated.</p>
<h3 id="heading-the-move-method">The Move Method</h3>
<p>Once the calling code has instantiated an object from the <code>Player</code> class, the calling code is able to execute the code within the Move method by appropriately calling the <code>Move</code> method on the relevant object.</p>
<p>The <code>Move</code> method is accessible to code from outside of the class in which it resides because it has a <code>public</code> access modifier. If the method had, for example, a private access modifier, this method would only be accessible from within the class in which it resides.</p>
<p>When the <code>Move</code> method is executed by calling code, two arguments of type <code>double</code>, must be passed into the move method because the <code>Move</code> method contains two parameters of type <code>double</code>.</p>
<p>Below (in figure 62) is an example of calling code instantiating an object from the <code>Player</code> class and subsequently calling the Move method on the relevant instantiated player object.</p>
<p>Figure 62.</p>
<pre><code class="lang-csharp">Player player = <span class="hljs-keyword">new</span> Player(<span class="hljs-string">"Bob"</span>);
player.Move(<span class="hljs-number">10.54</span>, <span class="hljs-number">18.43</span>);
</code></pre>
<p>For more information on C# Classes please view the video below:</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/6rlUl5T2Sck" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>And below you can find a full video series on C# classes:</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=6rlUl5T2Sck&amp;list=PL4LFuHwItvKY76WTDhfGAwrpLZaSxF9fS">C# Classes Video Series</a></p>
<h2 id="heading-c-structs">C# Structs</h2>
<p>The <code>struct</code> keyword is used to define a data structure in C# that is a value type. Structs are similar to classes in many respects – for example, you can use both structs and classes to represent data structures that can contain data members and related behavioural functionality expressed within methods.</p>
<h3 id="heading-key-differences-between-a-class-and-a-struct">Key differences between a Class and a Struct.</h3>
<ul>
<li>The main difference is that a class is a reference type and a struct is a value type. Structs implicitly inherit from the <code>System.ValueType</code> abstract class (which in turn inherits from the <code>System.Object</code> class), while reference types inherit directly from the <code>System.Object</code> type.</li>
<li>A struct is a better choice than a class when representing data structures that store small amounts of data. Another good reason to use a struct is if you need to store small amounts of data in the relevant data structure and where a vast number of objects derived from the relevant struct are being dealt with in code.</li>
<li>You can instantiate an object from a struct using the <code>new</code> keyword just like you would when instantiating an object from a class. But the <code>new</code> keyword is not required when declaring and initialising a struct before you can use it in code.</li>
<li>In C# certain value type primitives are represented as structs, for example the <code>int</code> alias represents the <code>System.Int32</code> struct, the <code>bool</code> alias represents the <code>System.Bool</code> struct, and the <code>float</code> alias represents <code>System.Single</code> struct.</li>
</ul>
<h3 id="heading-use-a-struct-in-code">Use a Struct in Code</h3>
<p>Below (depicted in figure 63) is an example of code that uses a struct to store the specifications for a pattern. The pattern is denoted by a circle that is drawn within a square.</p>
<p>The <code>Radius</code> field stores the value that denotes the radius of the circle, which also determines the size of the square. The <code>InnerSymbol</code> field denotes the <code>char</code> value printed to the screen that is used for depicting the inner circle. The <code>OuterSymbol</code> field denotes the <code>char</code> value printed to the screen that is used for depicting the outer square in the overall pattern.</p>
<p>Figure 63.</p>
<pre><code class="lang-csharp">Console.WriteLine(<span class="hljs-string">"Please enter the radius of the circle"</span>);
<span class="hljs-keyword">double</span> radius = Convert.ToDouble(Console.ReadLine());

CircleInSquare circleInSquare;
circleInSquare.Radius = radius;
circleInSquare.InnerSymbol = <span class="hljs-string">'0'</span>;
circleInSquare.OuterSymbol = <span class="hljs-string">'1'</span>;
circleInSquare.Draw();

<span class="hljs-comment">//Output</span>

<span class="hljs-comment">// 11111111111111111111111111111111111111111</span>
<span class="hljs-comment">// 11111111111111000000000000011111111111111</span>
<span class="hljs-comment">// 11111111110000000000000000000001111111111</span>
<span class="hljs-comment">// 11111111000000000000000000000000011111111</span>
<span class="hljs-comment">// 11111100000000000000000000000000000111111</span>
<span class="hljs-comment">// 11110000000000000000000000000000000001111</span>
<span class="hljs-comment">// 11100000000000000000000000000000000000111</span>
<span class="hljs-comment">// 11000000000000000000000000000000000000011</span>
<span class="hljs-comment">// 11000000000000000000000000000000000000011</span>
<span class="hljs-comment">// 11000000000000000000000000000000000000011</span>
<span class="hljs-comment">// 11000000000000000000000000000000000000011</span>
<span class="hljs-comment">// 11000000000000000000000000000000000000011</span>
<span class="hljs-comment">// 11000000000000000000000000000000000000011</span>
<span class="hljs-comment">// 11000000000000000000000000000000000000011</span>
<span class="hljs-comment">// 11100000000000000000000000000000000000111</span>
<span class="hljs-comment">// 11110000000000000000000000000000000001111</span>
<span class="hljs-comment">// 11111100000000000000000000000000000111111</span>
<span class="hljs-comment">// 11111111000000000000000000000000011111111</span>
<span class="hljs-comment">// 11111111110000000000000000000001111111111</span>
<span class="hljs-comment">// 11111111111111000000000000011111111111111</span>
<span class="hljs-comment">// 11111111111111111111111111111111111111111</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">struct</span> CircleInSquare
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> Radius;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">char</span> InnerSymbol;
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">char</span> OuterSymbol;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">CircleInSquare</span>(<span class="hljs-params"><span class="hljs-keyword">double</span> radius, <span class="hljs-keyword">char</span> innerSymbol, <span class="hljs-keyword">char</span> outerSymbol</span>)</span>
    {
        Radius = radius;
        InnerSymbol = innerSymbol;
        OuterSymbol = outerSymbol;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">WriteMemberValuesToScreen</span>(<span class="hljs-params"></span>)</span>
    {
        Console.WriteLine(
            <span class="hljs-string">$"Radius = <span class="hljs-subst">{Radius}</span>, InnerSymbol = '<span class="hljs-subst">{InnerSymbol}</span>', OuterSymbol = '<span class="hljs-subst">{OuterSymbol}</span>'"</span>
        );
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">Draw</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">double</span> radiusInner = Radius - <span class="hljs-number">0.5</span>;
        <span class="hljs-keyword">double</span> radiusOuter = Radius + <span class="hljs-number">0.5</span>;

        Console.WriteLine();

        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">double</span> y = Radius; y &gt;= -Radius; --y)
        {
            <span class="hljs-keyword">for</span> (<span class="hljs-keyword">double</span> x = -Radius; x &lt; radiusOuter; x += <span class="hljs-number">0.5</span>)
            {
                <span class="hljs-keyword">double</span> <span class="hljs-keyword">value</span> = x * x + y * y;

                <span class="hljs-keyword">if</span> (<span class="hljs-keyword">value</span> &gt;= radiusInner * radiusInner)
                {
                    Console.Write(OuterSymbol);
                    System.Threading.Thread.Sleep(<span class="hljs-number">50</span>);
                }
                <span class="hljs-keyword">else</span>
                {
                    Console.Write(InnerSymbol);
                }
            }
            Console.WriteLine();
        }
    }
}
</code></pre>
<p>Note that as demonstrated in the example above (in figure 63), the <code>new</code> keyword does not need to be used when instantiating an object from a struct in C#.</p>
<p>A struct is a data structure in C# that is ideal for storing a small amount of values, for example that are needed for objects derived from the <code>CircleInSquare</code> struct.</p>
<p>As discussed above, structs are value types in C# which means they are handled more efficiently in memory, where the relevant data is stored in memory on the stack. If you needed to store a sufficiently large number of instances of objects derived from the <code>CircleInSquare</code> struct in a collection, this is where a performance advantage could be noticeably gained over a scenario where object instances derived from a class version of the <code>CircleInSquare</code> template are stored within a collection.</p>
<p>So for example in a game where perhaps vector information needs to be stored in a large collection to represent the position of a <code>player</code> object, you could use a struct to represent the data rather than a class. This would help the data be managed more efficiently in memory, which brings a performance advantage as well in terms of code execution.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/NVKGxzuBe8c" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-enums-and-switch-statements">Enums and Switch Statements</h2>
<h3 id="heading-introduction-to-enums">Introduction to Enums</h3>
<p>In C#, an enum, short for enumeration, is a value type that you can use to define a set of named integral constants. Enums are used to create human readable names for a set of related and unique values, making the code more readable.</p>
<h3 id="heading-use-an-enum-in-code">Use an Enum in Code</h3>
<p>To declare an enum, you use the <code>enum</code> C# keyword. In figure 64 is a code example demonstrating the use of an enum. You can see that months of the year are represented by an enum named <code>MonthOfYear</code>. Each of the twelve members of the <code>MonthOfYear</code> enum represents a unique month of the year. Each month’s associated integer value is ordered in ascending order by the chronological order in which they occur for a calendar year.</p>
<p>So <code>Jan</code> is given the value of <code>1</code>, <code>Feb</code> is given the value of <code>2</code>,  <code>Mar</code> is given the value of <code>3</code> and so on, until the last month <code>Dec</code>, which is given a value of <code>12</code> (the twelfth and final month of the calendar year).</p>
<p>A simple method named <code>OutputMonthMainFocus</code> is passed an enum value in order to output an appropriate narrative to the user that displays the user focus for the passed-in month argument.</p>
<p>Figure 64.</p>
<pre><code class="lang-csharp">OutputMonthMainFocus(<span class="hljs-string">"Focus for Jan:"</span>, MonthOfYear.Jan);
OutputMonthMainFocus(<span class="hljs-string">"Focus for Mar:"</span>, MonthOfYear.Mar);
OutputMonthMainFocus(<span class="hljs-string">"Focus for Dec:"</span>, MonthOfYear.Dec);

<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// Focus.for Jan: Health and fitness</span>
<span class="hljs-comment">// Focus.for Mar: Increase knowledge of calculus</span>
<span class="hljs-comment">// Focus for Dec: Spend more time with friends and family</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">OutputMonthMainFocus</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> prependedText, MonthOfYear month</span>)</span>
{
    <span class="hljs-keyword">switch</span> (month)
    {
        <span class="hljs-keyword">case</span> MonthOfYear.Jan:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Health and fitness"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Feb:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Learn Spanish"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Mar:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Increase knowledge of calculus"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Apr:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Getting up earlier"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.May:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Better work organisation"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Jun:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Volunteer work"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Jul:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Eating more vegetables"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Aug:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Travel to London"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Sep:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Learning to cook better"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Oct:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Learn to. surf"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Nov:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Be more productive"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Dec:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Spend more time with friends and family"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ArgumentException(<span class="hljs-string">"Invalid Month"</span>);
    }
}
</code></pre>
<h3 id="heading-using-a-switch-statement-in-code-with-an-enum">Using a switch Statement in Code with an enum</h3>
<p>You can see that the above <code>switch</code> statement depicted in figure 64 is similar to an <code>if/else</code> statement.</p>
<p>At the top of the <code>switch</code> statement is code that contains the <code>switch</code> keyword. Within the brackets following the <code>switch</code> keyword is the value that the <code>switch</code> operation compares to a series of values that are denoted by each <code>case</code> statement that's encapsulated within the <code>switch</code> code block.</p>
<p>Each <code>case</code> section is comparing the value within the brackets following the <code>switch</code> keyword to a value following each <code>case</code> keyword. When a match between the value within the brackets following the <code>switch</code> keyword and a value following one of the <code>case</code> keywords is found, the statement list within the matched case section is executed.</p>
<p>For example, where the first line in the calling code (that is code that calls the <code>OutputMonthMainFocus</code> method) is called, the statement in the first case section is executed. This is because <code>Month.Jan</code> is passed in as an argument to the <code>OutputMonthMainFocus</code> method and <code>Month.Jan</code> is a match against the value following the <code>case</code> keyword in the first <code>case</code> section.</p>
<p>Note that a <code>break</code> keyword or a <code>return</code> keyword (if appropriate) must be included as the bottom statement of each case section’s statement list.</p>
<p>Each case section is mutually exclusive. This means that in the code example depicted in figure 64 where a <code>break</code> keyword is included as the bottom statement in each <code>case</code> section, when a match occurs, only the statements within that matching <code>case</code> section are run. Once the statements within that <code>case</code> statement are run, the code breaks out of the <code>switch</code> code block. If there is any code below the <code>switch</code> code block, then that code will subsequently be run. No other code within that <code>switch</code> statement will be run after a match occurs.</p>
<p>If no matches are found within any of the <code>case</code> statements, the code within the <code>default</code> section is run.</p>
<p>You can see in the example in figure 64 that the code throws an <code>ArgumentException</code> if no values within the relevant <code>case</code> statements match the value passed into the <code>switch</code> statement.</p>
<h3 id="heading-associating-one-code-block-with-more-than-one-case">Associating One Code Block with More than One Case</h3>
<p>You could alter the <code>switch</code> statement as depicted in figure 65, so that more than one case statement is associated with a block of code (or lines of code). So if, for example, <code>Month.Jan</code> was passed into the <code>switch</code> statement, the code statements within the <code>Month.Mar</code> case section would run.</p>
<p>The same lines of code within the <code>Month.Mar</code> case section would also run where <code>Month.Feb</code> or <code>Month.Mar</code> are passed in as arguments to the <code>switch</code> statement. This happens because there are no lines of coded included within the <code>Month.Jan</code> case section and there are no lines of code included within the <code>Month.Feb</code> section. So if the <code>Month.Jan</code> or <code>Month.Feb</code> sections aren't matched, the code falls through to the <code>Month.Mar</code> case section and the lines of code within the <code>Month.Mar</code> case section are run.</p>
<p>Of course the lines of code within the <code>Month.Mar</code> section will also run if the <code>Month.Mar</code> case section is matched. So the logic for this is the same as the <code>if</code> statement depicted in figure 64b.</p>
<p>Figure 64b.</p>
<pre><code class="lang-csharp">MonthOfYear month = MonthOfYear.Feb;
<span class="hljs-keyword">string</span> prependedText = <span class="hljs-string">"Focus for Feb"</span>;
<span class="hljs-keyword">if</span> (month == MonthOfYear.Jan || month == MonthOfYear.Feb || month == MonthOfYear.Mar)
{
    Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Health and fitness"</span>);
    Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Learn Spanish"</span>);
    Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Increase knowledge of calculus"</span>);
}
</code></pre>
<p>Figure 65.</p>
<pre><code class="lang-csharp">OutputMonthMainFocus(<span class="hljs-string">"Focus for Jan:"</span>, MonthOfYear.Jan);
OutputMonthMainFocus(<span class="hljs-string">"Focus for Mar:"</span>, MonthOfYear.Feb);
OutputMonthMainFocus(<span class="hljs-string">"Focus for Dec:"</span>, MonthOfYear.Mar);

<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// Focus for Jan: Health and fitness</span>
<span class="hljs-comment">// Focus for Jan: Learn Spanish</span>
<span class="hljs-comment">// Focus for Jan: Increase knowledge of calculus</span>
<span class="hljs-comment">// Focus for Mar: Health and fitness</span>
<span class="hljs-comment">// Focus for Mar: Learn Spanish</span>
<span class="hljs-comment">// Focus for Mar: Increase knowledge of calculus</span>
<span class="hljs-comment">// Focus for Dec: Health and fitness</span>
<span class="hljs-comment">// Focus for Dec: Learn Spanish</span>
<span class="hljs-comment">// Focus for Dec: Increase knowledge of calculus</span>
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">OutputMonthMainFocus</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> prependedText, MonthOfYear month</span>)</span>
{
    <span class="hljs-keyword">switch</span> (month)
    {
        <span class="hljs-keyword">case</span> MonthOfYear.Jan:
        <span class="hljs-keyword">case</span> MonthOfYear.Feb:
        <span class="hljs-keyword">case</span> MonthOfYear.Mar:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Health and fitness"</span>);
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Learn Spanish"</span>);
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Increase knowledge of calculus"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Apr:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Getting up earlier"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.May:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Better work organisation"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Jun:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Volunteer work"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Jul:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Eating more vegetables"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Aug:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Travel to London"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Sep:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Learning to cook better"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Oct:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Learn to. surf"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Nov:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Be more productive"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">case</span> MonthOfYear.Dec:
            Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{prependedText}</span> Spend more time with friends and family"</span>);
            <span class="hljs-keyword">break</span>;
        <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ArgumentException(<span class="hljs-string">"Invalid Month"</span>);
    }
}
</code></pre>
<h3 id="heading-using-strings-in-switch-statements">Using Strings in switch Statements</h3>
<p>The example depicted in figure 64, specifically deals with the value list within an enum type. You can also, of course, use a <code>switch</code> statement to evaluate the values for any C# data type.</p>
<p>For example, in figure 66, values of the string data type are evaluated instead of the numeric values contained within an enum. figure 66.</p>
<pre><code class="lang-csharp">OutputMonthMainFocus(<span class="hljs-string">"Focus for Jan:"</span>, <span class="hljs-string">"JAN"</span>);
OutputMonthMainFocus(<span class="hljs-string">"Focus for Mar:"</span>, <span class="hljs-string">"MAR"</span>);
OutputMonthMainFocus(<span class="hljs-string">"Focus for Dec:"</span>, <span class="hljs-string">"DEC"</span>);
<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// Focus for Jan: Health and fitness</span>
<span class="hljs-comment">// Focus for Mar: Increase knowledge of calculus</span>
<span class="hljs-comment">// Focus for Dec: Spend more time with friends and family</span>
</code></pre>
<p>Note that you can use <code>if/else if/else</code> conditional logic where appropiate in order to replace a <code>switch</code> statement, however it is better to use a <code>switch</code> statement when there are a large number of logical conditions to evaluate. This is because a <code>switch</code> statement is more readible in this scenario.</p>
<p>You can watch the YouTube videos below to learn more about switch statements and enums.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/XTDEYQUymt8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/1248C0V_yHs" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-inheritance-in-c">Inheritance in C</h2>
<p>C# is an object-oriented programming language. The principles of object-oriented programming are encapsulation, inheritance, polymorphism, and abstraction.</p>
<p>Inheritance is where one class is based on another class. It is important to note that multiple inheritance is not permitted in C#. A class in C# can inherit from multiple interfaces but not multiple classes at one time. We'll discuss interfaces in the next section of this handbook along with the principle of abstraction.</p>
<p>So if, for example, the <code>ManagingDirector</code> class is based on the <code>Manger</code> class, which in turn is based on the <code>Employee</code> class, in C# you cannot implement the code like in the example below (in figure 67) in order to express this inheritance hierarchy.</p>
<p>Figure 67.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">ManagingDirector</span> : <span class="hljs-title">Manager</span>, <span class="hljs-title">Employee</span>
{
    <span class="hljs-comment">// code goes here</span>
}
</code></pre>
<p>In C++, this type of multiple inheritance is permitted. But in C#, only single inheritance is permitted.</p>
<p>In C# you are, however, still able to express that the <code>ManagingDirector</code> class inherits from the <code>Manager</code> class that in turn inherits from the <code>Employee</code> class – but you have to do this in a specific way.</p>
<p>The example below (in figure 68) depicts how this specific inheritance hierarchy can be expressed in C#.</p>
<p>Figure 68.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Manager</span>:<span class="hljs-title">Employee</span>
{
    <span class="hljs-comment">// code goes here</span>
} 
<span class="hljs-keyword">public</span> ManagingDirector:Manager
{    
    <span class="hljs-comment">// code goes here</span>
}
</code></pre>
<p>So C# only supports single inheritance for classes, but you can achieve multiple inheritance by implementing code in a certain way in C#. The example above (in figure 68) shows you how to do this.</p>
<h2 id="heading-abstraction-in-c">Abstraction in C</h2>
<p>Abstraction is another principle of object-oriented programming. It is a concept that is often confused with another one of the principles of object-oriented programming, namely, encapsulation.</p>
<p>Abstraction can be defined as the inclusion of essential design related code but no implementation detail. The implementation detail is denoted by the lines of code within a method, and the abstraction of that method is the method’s method signature.</p>
<p>In the simplified example below (in figure 69), you can see a method named <code>LogData</code> that is responsible for either printing data to the console screen or printing data to a predefined local file.</p>
<p>Figure 69</p>
<pre><code class="lang-csharp"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">LogData</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> data</span>)</span>
{
    LogToScreen(data);
}
</code></pre>
<p>The abstraction of this method would be the method signature that could be represented inside an interface like in the example below depicted in figure 70:</p>
<p>Figure 70.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">interface</span> <span class="hljs-title">ILogging</span>
{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">LogData</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> data</span>)</span>;
}
</code></pre>
<p>The <code>LogData</code> method could reside inside a class named <code>Logging</code> that implements the <code>ILogging</code> interface. When a class implements an interface in C# this means that the class must contain and implement all the methods that are defined within the relevant <code>interface</code>.</p>
<p>See below (in figure 71) an example of the <code>Logging</code> class implementing the <code>ILogging</code> interface.</p>
<p>Figure 71</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Logging</span> : <span class="hljs-title">ILogging</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">LogData</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> data</span>)</span>
    {
        LogToScreen(data);
    }
}
</code></pre>
<p>The <code>ILogging</code> interface can be described as an abstraction of the <code>Logging</code> class. In C#, the calling code does not need to know (as it were) about the the code implementation of the <code>LogData</code> method. The calling code only needs to know about the type definition. The type definition is the abstraction of the <code>Logging</code> class.</p>
<p>In the example below (in figure 72) you can see an example of calling code instantiating an object from the <code>Logging</code> user defined type. Notice how the type definition can be implemented using the <code>ILogging</code> interface. This means the calling code will know about the <code>LogData</code> method at compile time, but will not know anything about its implementation.</p>
<p>Figure 72.</p>
<pre><code class="lang-csharp">ILogging logging = <span class="hljs-keyword">new</span> Logging();
logging.LogData(<span class="hljs-string">"Data to be logged."</span>);
</code></pre>
<p>Now you could create many logging classes with different implementations of the <code>LogData</code> method.</p>
<p>For example, currently the <code>Logging</code> class contains an implementation of the <code>LogData</code> method that logs data to the console screen. Let’s say a requirement emerges where you want to log the data to the a predefined file. To do this you could simply create a new class that implements the <code>ILogging</code> interface, where the code within the new class contains code that logs the relevant data to a predefined file.</p>
<p>The example below (in figure 73) depicts the new class. For the sake of simplicity let’s name this class <code>Logging2</code>.</p>
<p>Figure 73.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">Logging2</span> : <span class="hljs-title">ILogging</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">LogData</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> data</span>)</span>
    {
        LogToFile(data);
    }
}
<span class="hljs-comment">// Calling code</span>
ILogging logging = <span class="hljs-keyword">new</span> Logging2();
logging.LogData(<span class="hljs-string">"Data to be logged."</span>);
</code></pre>
<p>The calling code that implements the <code>LogData</code> method in the <code>Logging</code> class would look very similar to when the <code>LogData</code> method is called on an object instantiated from the <code>Logging2</code> class.</p>
<p>In fact you could abstract the instantiation of the relevant <code>logging</code> object into its own factory class like you see below in figure 74. So through the use of an interface we are able to further abstract our code, by abstracting the instantiation process of the logging classes.</p>
<p>Figure 74.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">LoggingFactory</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> ILogging <span class="hljs-title">GetLoggingObject</span>(<span class="hljs-params"><span class="hljs-keyword">bool</span> toScreen</span>)</span>
    {
        <span class="hljs-keyword">if</span> (toScreen)
        {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Logging();
        }
        <span class="hljs-keyword">else</span>
        {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Logging2();
        }
    }
}
</code></pre>
<p>The calling code could now be implemented as is depicted below in figure 75.</p>
<p>Figure 75.</p>
<pre><code class="lang-csharp">ILogging logging = LoggingFactory.GetLoggingObject(<span class="hljs-literal">true</span>);
logging.LogData(<span class="hljs-string">"Log data to screen"</span>);
</code></pre>
<p>And the calling code could be implemented as is depicted in figure 76 for logging data to a predefined file.</p>
<p>Figure 76.</p>
<pre><code class="lang-csharp">ILogging logging = LoggingFactory.GetLoggingObject(<span class="hljs-literal">false</span>);
logging.LogData(<span class="hljs-string">"Log data to file"</span>);
</code></pre>
<p>We have abstracted away the implementation for both the <code>LogData</code> method as well as the instantiation of the <code>logging</code> object. This is a very basic example of how the principle of abstraction can be implemented using C# in order to create a separation of concerns.</p>
<p>You can of course create many layers of abstraction using similar techniques and various design patterns. Some key driving forces behind how you abstract your code should be better code reuse, better code readability, easier maintenance of code, design extensibility, and to facilitate better unit testing.</p>
<p>In this book, I haven't delved deep into object-oriented principles. For a more detailed explanation of object-oriented programming using C#, you can check out the videos in the playlist link below. In the videos in this playlist the object-orientied principles of encapsulation, inheritance, polymorphism and abstraction are explained and many practicle code eamples are included.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/HcjOcwMS43w" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>For a full video series on object-oriented programming in C#, please visit here:</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=HcjOcwMS43w&amp;list=PL4LFuHwItvKYD0e60jNOtT6mFKqFMH1u_">Full Video Series on Object-oriented Programming using C#</a></p>
<h2 id="heading-c-exception-handling">C# Exception Handling</h2>
<p>One of your core design criterion when designing an application should be ensuring that your application is as robust as possible.</p>
<p>In order to do this, you'll need to devise and implement a well-designed exception handling strategy. C# makes this fairly easy through the use of <code>try/catch/finally</code> blocks.</p>
<p>Exception handling is used to prevent an application from crashing. As a good rule, you should try as much as possible to prevent exceptions from being thrown through code, and only use built-in C# <code>try/catch</code> blocks to handle exceptions under truly exceptional circumstances.</p>
<p>A<code>try/catch'</code> block allows you to wrap certain code that you know, under certain exceptional circumstances, can result in your application crashing. By understanding the relevant exceptional circumstances that may cause your application to crash, you can implement the appropriate exception handling functionality.</p>
<p>You can catch specific exceptions through the <code>catch</code> section of the <code>try/catch</code> block. Then you can handle the exception appropriately either by handing the exception within the relevant catch block or by throwing the exception up the stack to be handled appropriately at a further point further up the execution stack.</p>
<p>In this very basic calculator application code example (depicted in figure 77), a method named <code>Calculate</code> is implemented to carry out the calculations.</p>
<p>Figure 77.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">try</span>
{
    <span class="hljs-keyword">int</span> result1 = Calculate(<span class="hljs-number">200000</span>, <span class="hljs-number">500000</span>, <span class="hljs-string">'*'</span>); <span class="hljs-comment">// OverFlowException occures</span>
    <span class="hljs-keyword">int</span> result2 = Calculate(<span class="hljs-number">5</span>, <span class="hljs-number">2</span>, <span class="hljs-string">'^'</span>); <span class="hljs-comment">// InvalidOperation exception will occur within the Calculate method</span>
    <span class="hljs-keyword">int</span> result3 = Calculate(<span class="hljs-number">4</span>, <span class="hljs-number">0</span>, <span class="hljs-string">'/'</span>); <span class="hljs-comment">// Attempted to divide by zero</span>
    Console.WriteLine(result1);
}
<span class="hljs-keyword">catch</span> (ArgumentException)
{
    WriteToScreen(<span class="hljs-string">"The operation symbol input is not recognised by this application"</span>);
}
<span class="hljs-keyword">catch</span> (Exception ex)
{
    WriteToScreen(ex.Message);
}
<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">Calculate</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> operand1, <span class="hljs-keyword">int</span> operand2, <span class="hljs-keyword">char</span> operatorSymbol</span>)</span>
{
    <span class="hljs-keyword">int</span> result = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">try</span>
    {
        <span class="hljs-keyword">switch</span> (operatorSymbol)
        {
            <span class="hljs-keyword">case</span> <span class="hljs-string">'+'</span>:
                result = operand1 + operand2;
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'-'</span>:
                result = operand1 - operand2;
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'*'</span>:
                <span class="hljs-keyword">checked</span>
                {
                    result = operand1 * operand2;
                }
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>:
                result = operand1 / operand2;
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">default</span>:
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidOperationException();
        }
    }
    <span class="hljs-keyword">catch</span> (OverflowException)
    {
        WriteToScreen(
            <span class="hljs-string">"The result of the calculation exceeded that max value for the int data type"</span>
        );
    }
    <span class="hljs-keyword">catch</span> (InvalidOperationException ex)
    {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ArgumentException(
            <span class="hljs-string">$"<span class="hljs-subst">{<span class="hljs-keyword">nameof</span>(operatorSymbol)}</span> is invalid"</span>,
            <span class="hljs-keyword">nameof</span>(operatorSymbol),
            ex
        );
    }
    <span class="hljs-keyword">return</span> result;
}
</code></pre>
<p>With the first call to the <code>Calculate</code> method in the above example, the calculation will yield a result that is too large to be supported by the integer data type. This means that an <code>OverFlowException</code> will be initially flagged by the C# compiler.</p>
<p>Within the <code>OverFlowException</code> catch filter in the code example depicted in figure 77, code is implemented that handles the exception locally within the <code>Calculate</code> method. This means the exception is not thrown up the stack to be handled within the calling method. The exception handling code in the <code>OverFlowException</code> catch block is simply logging a message to a file through a custom <code>LogException</code> method.</p>
<p>With the second call to the <code>Calculate</code> method, an invalid operator (that is <code>^</code>) is passed to the <code>Calculate</code> method. In the default part of the relevant <code>switch</code> statement, the code is throwing an <code>InvalidOperation</code> exception which is an exception type that is built into the C# language. Within the <code>try/catch</code> block is a <code>catch</code> filter for specifically catching this <code>InvalidOperation</code> exception.</p>
<p>Within the <code>catch</code> block, the code is throwing a new <code>ArgumentException</code> exception which is subsequently being handled within the calling method (which in this case is the <code>Main</code> method, the entry point of this application). In the relevant code example top-level-statements are enabled which means the <code>Main</code> is not present in the code but as discussed earlier, the <code>Main</code> method is added behind the scenes and encapsulates the calling code which is expressed in this example as top-level-statements.</p>
<p>The <code>Main</code> method contains an <code>ArgumentException</code> catch section. In this <code>catch</code> section, the exception is being handled by outputting an informative message to the user.</p>
<p>Arguably this type of exception would be best handled in code rather than using <code>try/catch</code> code for this purpose. You could, for example, validate the operator before the <code>Calculate</code> method is called. If the operator is entered by the user incorrectly, output an informative message to them. The user can then alter their input appropriately.</p>
<p>So in order to use validation rather than <code>try/catch</code> code in this scenario, the calling code could be changed to what you see in the example below in figure 78:</p>
<p>Figure 78.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">int</span> result = <span class="hljs-number">0</span>;
Console.WriteLine(<span class="hljs-string">"Please enter a whole number value for the first operand"</span>);
<span class="hljs-keyword">int</span> operand1 = <span class="hljs-keyword">int</span>.Parse(Console.ReadLine());
Console.WriteLine(<span class="hljs-string">"Please enter a whole number value for the second operand"</span>);
<span class="hljs-keyword">int</span> operand2 = <span class="hljs-keyword">int</span>.Parse(Console.ReadLine());
Console.WriteLine(<span class="hljs-string">"Please enter a valid operator symbol ('+','-','*','/')"</span>);
<span class="hljs-keyword">char</span> operatorSymbol = <span class="hljs-keyword">char</span>.Parse(Console.ReadLine());

<span class="hljs-keyword">if</span> (
    operatorSymbol != <span class="hljs-string">'+'</span>
    || operatorSymbol != <span class="hljs-string">'-'</span>
    || operatorSymbol != <span class="hljs-string">'*'</span>
    || operatorSymbol != <span class="hljs-string">'/'</span>
)
{
    WriteToScreen(
        <span class="hljs-string">"Incorrect operator input. The operator symbol must be one of the following ('+'’','-','*','/') "</span>
    );
}
<span class="hljs-keyword">else</span>
{
    result = Calculate(operand1, operand2, operatorSymbol);
    WriteToScreen(result.ToString());
}

<span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">Calculate</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> operand1, <span class="hljs-keyword">int</span> operand2, <span class="hljs-keyword">char</span> operatorSymbol</span>)</span>
{
    <span class="hljs-keyword">int</span> result = <span class="hljs-number">0</span>;
    <span class="hljs-keyword">try</span>
    {
        <span class="hljs-keyword">switch</span> (operatorSymbol)
        {
            <span class="hljs-keyword">case</span> <span class="hljs-string">'+'</span>:
                result = operand1 + operand2;
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'-'</span>:
                result = operand1 - operand2;
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'*'</span>:
                <span class="hljs-keyword">checked</span>
                {
                    result = operand1 * operand2;
                }
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>:
                result = operand1 / operand2;
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">default</span>:
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidOperationException();
        }
    }
    <span class="hljs-keyword">catch</span> (OverflowException)
    {
        WriteToScreen(
            <span class="hljs-string">"The result of the calculation exceeded that max value for the int data type"</span>
        );
    }
    <span class="hljs-keyword">catch</span> (InvalidOperationException ex)
    {
        <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ArgumentException(
            <span class="hljs-string">$"<span class="hljs-subst">{<span class="hljs-keyword">nameof</span>(operatorSymbol)}</span> is invalid"</span>,
            <span class="hljs-keyword">nameof</span>(operatorSymbol),
            ex
        );
    }
}
<span class="hljs-keyword">return</span> result;
</code></pre>
<p>In this case, it's unnecessary to use exception handling, and instead you can use conditional code to validate the operator symbol before the <code>Calculate</code> method is even called.</p>
<p>It is important to note that all <code>Exception</code> types – including the ones that have been used in these code examples – are derived from the <code>Exception</code> type.</p>
<p>The <code>Exception</code> type is built into C#. All <code>Exception</code> types in C# are derived from the base <code>Exception</code> type. An exception inheritance hierarchy has been deliberately designed and implemented in C#. The exceptions I've used in the examples in this section of the book are <code>OverflowException</code>, <code>InvalidOperationException</code> and <code>ArgumentException</code>. These exception types are derived from the base <code>Exception</code> type.</p>
<p>The exception type hierarchy in C# means that when there are multiple exception filters within a <code>try/catch</code> block, the more derived exception types must be included first within the relevant list of catch filters.</p>
<p>For example, in the examples depicted in this section, the <code>ArgumentException</code> appears before the <code>Exception</code> catch filter. If the <code>Exception</code> catch filter appeared before the <code>ArgumentException</code> filter, this would mean that the code within the <code>ArgumentException</code> catch filter would never be called. So it's important that the <code>Exception</code> catch filter appear after the <code>ArgumentException</code> catch filter.</p>
<p>Note that in many cases you'll want to include a <code>finally</code> section in your <code>try/catch</code> code. This <code>finally</code> section is always called when the relevant <code>try/catch</code> code is executed. So the code included in the <code>finally</code> section is run when code within the <code>try</code> section causes an exception to occur (resulting in code within the relevant catch filter being executed) or even if no exceptions occur due to code included within the relevant <code>try</code> section. This makes the <code>finally</code>  section ideal for including clean up code, that is used for cleaning up resources (for example database connection objects) that are no longer needed.</p>
<p>For more detail on exception handling in C#, you can check out the videos in the playlist below.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/mpdg6SAaoZ4" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>For a full video series on exception handling in C#, go here:</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=mpdg6SAaoZ4&amp;list=PL4LFuHwItvKaHOvj1B5DhTnH0MJ1JFJzr">Full Video Series on Exception Handling in C#</a></p>
<p>For a full video series on file handling in C#, go here:</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=DHgU_tAC85U&amp;list=PL4LFuHwItvKaqc6w0awyyNGfkzU4ke5fu">Full Video Series on File Handling in C#</a></p>
<h2 id="heading-c-delegates">C# Delegates</h2>
<p>Delegates can be described as type safe function pointers. With a delegate, you can define a method definition that includes a parameter list as well as a return type (if no return type is included in the delegate definition, the <code>void</code> keyword must be included in place of a data type).</p>
<p>Methods that conform (appropriately in terms of their method signatures) to that defined delegate type can be referenced by the compatible delegate type. A variable can be assigned the relevant delegate and you can then use the variable to invoke any appropriate method that is referenced by the delegate.</p>
<p>In the code example depicted in figure 79 below, a delegate is defined and named <code>LogDel</code>. With the declaration of the <code>LogDel</code> delegate, a method definition for a method is declared. The method definition in this case represents any method that accepts a string argument and does not return a value (which is denoted by the <code>void</code> keyword).</p>
<p>The C# <code>void</code> keyword is used in the delegate definition to signify that any method referenced by this delegate must not return a value. Of course you can declare a delegate for a method that does return a value (in which case the delegate definition would include the appropriate data type instead of the <code>void</code> keyword).</p>
<p>In this case, however, a delegate is defined to provide an abstraction for a method that accepts a string argument and does not return a value.</p>
<p>In the code example depicted in figure 79, you can see how a delegate is used to create flexibility where calling code can reuse the <code>LogDel</code> delegate to log text to the console screen or log the text to a text file. Using this delegate definition the calling code can even implement what is known as a multi-cast delegate.</p>
<p>In this case, an instantiation of the <code>LogDel</code> delegate type is used to combine the functionality of a method that logs text to the screen as well as a method that logs text to a file. In the code, the <code>+</code> operator is used in between two delegates and the result is assigned to a delegate named <code>multiLogDel</code>.</p>
<p>When the <code>multiLogDel</code> delegate is invoked, the text is logged both to the console screen as well as to the text file. So delegates can be used to call multiple methods (that are appropriately defined where the method definitions match the delegate definition) through one invocation of the delegate instantiation.</p>
<p>Also, through the delegate, you can invoke functionality for just one of the methods – in this example either <code>LogTextToScreen</code> or <code>LogTextToFile</code>.</p>
<p>So delegates provide a type safe, flexible abstraction over methods that you can use to call one or multiple methods that conform to a specified method definition.</p>
<p>Figure 79.</p>
<pre><code class="lang-csharp">Log log = <span class="hljs-keyword">new</span> Log();
LogDel LogTextToScreenDel,
    LogTextToFileDel;
LogTextToScreenDel = <span class="hljs-keyword">new</span> LogDel(log.LogTextToScreen);
LogTextToFileDel = <span class="hljs-keyword">new</span> LogDel(log.LogTextToFile);
LogDel multiLogDel = LogTextToScreenDel + LogTextToFileDel;
Console.WriteLine(<span class="hljs-string">"Please enter your name"</span>);
<span class="hljs-keyword">var</span> name = Console.ReadLine();
LogText(multiLogDel, name);
Console.ReadKey();
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">LogText</span>(<span class="hljs-params">LogDel logDel, <span class="hljs-keyword">string</span> text</span>)</span>
{
    logDel(text);
}
<span class="hljs-function"><span class="hljs-keyword">delegate</span> <span class="hljs-keyword">void</span> <span class="hljs-title">LogDel</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> text</span>)</span>;

<span class="hljs-keyword">class</span> <span class="hljs-title">Log</span>
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">LogTextToScreen</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> text</span>)</span>
    {
        Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{DateTime.Now}</span>: <span class="hljs-subst">{text}</span>"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">LogTextToFile</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> text</span>)</span>
    {
        <span class="hljs-keyword">using</span> (
            StreamWriter sw = <span class="hljs-keyword">new</span> StreamWriter(
                Path.Combine(AppDomain.CurrentDomain.BaseDirectory, <span class="hljs-string">"Log.txt"</span>),
                <span class="hljs-literal">true</span>
            )
        )
        {
            sw.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{DateTime.Now}</span>: <span class="hljs-subst">{text}</span>"</span>);
        }
    }
}
</code></pre>
<p>For more detail on delegates, you can watch the videos in the playlist below.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/5YTqMe2GC5U" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>For a full video series on delegates in C#, go here:</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=5YTqMe2GC5U&amp;list=PL4LFuHwItvKZwUnVL2KKvfYxNMVo-TQAB">Full Video Series on C# Delegates</a></p>
<h2 id="heading-c-events">C# Events</h2>
<p>Events can be used in C# to notify other classes or objects when, for example, a condition is met within the class or object in which that event resides. When the condition is met within the class or object that contains the event, the event can be raised. This means that those classes or objects that have elected to receive notifications when the relevant event is raised will receive those notifications.</p>
<p>The classes or objects elect to receive these notifications by subscribing in code to the event that resides in the class or object that contains the event. The class or object that contains the event is known as the publisher, and the classes or objects that have subscribed to recieve notifications when the relevant event is raised are known as the subscribers.</p>
<p>In the example depicted in figure 80 below, the publisher is the class named <code>GuessNumberGame</code>. You can see that an event named <code>GameEvent</code> has been published within this class. In this simple example, the subscription to the <code>GameEvent</code> class is made within the entry point or <code>Main</code> method of the application (shown in this example in the top-level-statements of the application).</p>
<p>Here, this is for the sake of simplicity – but in a real-world application you may have many subscriber classes subscribing to the event within the publisher class.</p>
<p>So within the calling code, a subscription to the <code>GameEvent</code> event is made through the use of the <code>+=</code> operator. This operator is used when a subscription to an event is made in C# code.</p>
<p>On the right hand side of the <code>+=</code> operator is the name of a method that is designated to handle the event when the event is raised. So this event handling method resides within the subscriber code.</p>
<p>We used a built-in C# generic delegate to define the <code>GameEvent</code> event. This in effect defines the the method definition for the method or methods that are designated to handle the event.</p>
<p>The <code>EventHandler</code> delegate provides a definition for a method that contains two parameters. One is defined as <code>object</code>, and the other is defined as a generic type argument that is passed in as an argument to the <code>EventHandler</code> delegate at compile time within the publisher class where the event is declared.</p>
<p>So you can see in the calling code, a method named <code>EventHandlerMethod</code> is defined that contains an argument of type <code>object</code>. There's also an object defined as the data type argument passed into the type parameter for the built-in generic <code>EventHandler</code> delegate, when the <code>GameEvent</code> is declared inside the publisher class.</p>
<p>So when the relevant condition is met within the <code>OnCorrectNumberGuessed</code> method, the <code>GameEvent</code> event is raised. This, in effect, results in the <code>EventHandlerMethod</code> being executed within the calling code, or within the subscriber's code, if you like.</p>
<p>The code in figure 80 is a simple game. The user gets three chances to guess a random number between 1 and 4 (including 4), generated within the <code>GuessNumberGame</code> class.</p>
<p>If the user guesses the correct number, the <code>GameEvent</code> event is raised and the code within the <code>EventHandlerMethod</code> is run. This results in outputted text being displayed to the user, informing them that they have guessed the correct number and have therefore won the game.</p>
<p>So when the user guesses the correct number, the following text is outputted to the console screen: <code>You guessed it!! Well done! :)</code>.</p>
<p>As we discussed before, the <code>+=</code> operator is used for subscribers to subscribe to an event within the publisher class or object. This lets them receive notifications when the event is raised through code within the publisher class or object.</p>
<p>After the <code>while</code> loop code, there's a line of code where the subscriber unsubscribes from the event. This is important, as it prevents possible memory leaks from occurring.</p>
<p>To unsubscribe from the event, you can use the <code>-=</code> C# operator:</p>
<p>Figure 80.</p>
<pre><code class="lang-csharp">Console.WriteLine(<span class="hljs-string">"Guess the number of which the computer is thinking. Is it 1,2,3 or 4?"</span>);
Console.WriteLine();
<span class="hljs-keyword">int</span> counter = <span class="hljs-number">0</span>;
<span class="hljs-keyword">bool</span> gameIsWon = <span class="hljs-literal">false</span>;
GuessNumberGame guessNumberGame = <span class="hljs-keyword">new</span> GuessNumberGame();
guessNumberGame.GameEvent += EventHandlerMethod;
<span class="hljs-keyword">do</span>
{
    counter++;
    Console.WriteLine(<span class="hljs-string">"Please input your number choice"</span>);
    <span class="hljs-keyword">int</span> userGuessedNumber = Int32.Parse(Console.ReadLine());
    guessNumberGame.CompareUsersNumber(userGuessedNumber);
} <span class="hljs-keyword">while</span> (gameIsWon == <span class="hljs-literal">false</span> &amp;&amp; counter &lt; <span class="hljs-number">3</span>);
guessNumberGame.GameEvent -= EventHandlerMethod;
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">EventHandlerMethod</span>(<span class="hljs-params"><span class="hljs-keyword">object</span> sender, GuessNumberDataEventArgs args</span>)</span>
{
    Console.WriteLine(args.GuessNumberGameOutputMessage);
    gameIsWon = <span class="hljs-literal">true</span>;
}

<span class="hljs-keyword">class</span> <span class="hljs-title">GuessNumberGame</span>
{
    Random rnd = <span class="hljs-keyword">new</span> Random();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">readonly</span> <span class="hljs-keyword">int</span> generatedRandomNumber = <span class="hljs-number">0</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">GuessNumberGame</span>(<span class="hljs-params"></span>)</span>
    {
        <span class="hljs-keyword">this</span>.generatedRandomNumber = rnd.Next(<span class="hljs-number">1</span>, <span class="hljs-number">5</span>);
        Console.WriteLine(<span class="hljs-string">"Computer Gen ="</span> + generatedRandomNumber);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">CompareUsersNumber</span>(<span class="hljs-params"><span class="hljs-keyword">int</span> guessedNumber</span>)</span>
    {
        <span class="hljs-keyword">if</span> (guessedNumber == <span class="hljs-keyword">this</span>.generatedRandomNumber)
        {
            OnCorrectNumberGuessed(
                <span class="hljs-keyword">new</span> GuessNumberDataEventArgs
                {
                    GuessNumberGameOutputMessage = <span class="hljs-string">"You guessed it!! Well done! :)"</span>
                }
            );
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">OnCorrectNumberGuessed</span>(<span class="hljs-params">GuessNumberDataEventArgs e</span>)</span>
    {
        EventHandler &amp; lt;
        GuessNumberDataEventArgs &amp; gt;
        handler = GameEvent;
        <span class="hljs-keyword">if</span> (handler != <span class="hljs-literal">null</span>)
        {
            handler(<span class="hljs-keyword">this</span>, e);
        }
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-keyword">event</span> EventHandler&lt;GuessNumberDataEventArgs&gt; GameEvent;

}
</code></pre>
<p>For more details on using C# Events and more code examples, you can check out the YouTube video below.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/QJJKMW3ErEw" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>For a full video series on events in C#, you can go here:</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=QJJKMW3ErEw&amp;list=PL4LFuHwItvKa3dr0NL732rnnOhcc3aEgG">Full Video Series on C# Events</a></p>
<h2 id="heading-c-generics">C# Generics</h2>
<p>Generics allow C# developers to reuse specific code (like that which exists within a method, class, or collection) in the context of multiple different C# data types.</p>
<p>You determine this data type context at compile time where, for example, you can pass a data type argument to a data type parameter that is contained within the definition of the method, class, or collection type.</p>
<p>A simple code example of this is the C# generic <code>List</code> type, which is a built-in collection you can use. You can strongly type a generic list at compile time with C# built-in data types like <code>int</code>, <code>string</code>, <code>char</code>, <code>bool</code>, <code>decimal</code>, <code>float</code>, <code>double</code> and so on, as well as user defined types, like those that are implemented using a class or a struct.</p>
<p>In the example depicted in figure 82, the generic list type is being used to store the grades of a university student. All of the grades are integers. When you look at the definition for the <code>List</code> generic type that is built into C#, you see the word <code>List</code> followed by angle brackets, with a <code>T</code> included within the angle brackets. So the generic built-in C# <code>List</code> type is defined as is depicted in figure 81.</p>
<p>The <code>T</code> is a placeholder representing the generic data type parameter, which you can use to pass a data type argument to the 'List' type at compile time in order to strongly type the list.</p>
<p>Generics means that type parameters are included in .NET. This makes it possible for you to design classes and methods that defer the specification of one or more types until the class or method is declared and instantiated by calling code.</p>
<p>Figure 81.</p>
<pre><code class="lang-csharp">List&lt;T&gt;
</code></pre>
<p>Figure 82.</p>
<pre><code class="lang-csharp">List&lt;<span class="hljs-keyword">int</span>&gt; grades = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">int</span>&gt;();
grades.Add(<span class="hljs-number">60</span>);
grades.Add(<span class="hljs-number">73</span>);
grades.Add(<span class="hljs-number">85</span>);
grades.Add(<span class="hljs-number">92</span>);
<span class="hljs-keyword">foreach</span> (<span class="hljs-keyword">int</span> grade <span class="hljs-keyword">in</span> grades)
{
    Console.Write(<span class="hljs-string">$"<span class="hljs-subst">{grade}</span>, "</span>);
}

<span class="hljs-comment">// Output: 60, 73, 85, 92,</span>
<span class="hljs-comment">// You could also use the generic list to store the subject names pertaining to the grades of the relevant</span>
<span class="hljs-comment">// student.</span>
List&lt;<span class="hljs-keyword">string</span>&gt; subjects = <span class="hljs-keyword">new</span> List&lt;<span class="hljs-keyword">string</span>&gt;();
subjects.Add(<span class="hljs-string">"Observational Astronomy"</span>);
subjects.Add(<span class="hljs-string">"Particle Physics"</span>);
subjects.Add(<span class="hljs-string">"Quantum mechanics"</span>);
subjects.Add(<span class="hljs-string">"Advanced Math"</span>);
</code></pre>
<p>You can also use the same generic list data type to store objects derived from a specific user defined type, implemented, for example, as a class in code.</p>
<p>So in the example in figure 83, the list data type is used to store a collection of 'student' objects:</p>
<p>Figure 83.</p>
<pre><code class="lang-csharp">List&lt;Student&gt; students = <span class="hljs-keyword">new</span> List&lt;Student&gt;();
students.Add(
    <span class="hljs-keyword">new</span> Student
    {
        Id = <span class="hljs-number">1</span>,
        Name = <span class="hljs-string">"Dale Jones"</span>,
        Grade = <span class="hljs-number">60</span>
    }
);
students.Add(
    <span class="hljs-keyword">new</span> Student
    {
        Id = <span class="hljs-number">2</span>,
        Name = <span class="hljs-string">"Gale Davis"</span>,
        Grade = <span class="hljs-number">89</span>
    }
);
students.Add(
    <span class="hljs-keyword">new</span> Student
    {
        Id = <span class="hljs-number">3</span>,
        Name = <span class="hljs-string">"Debbie Hill"</span>,
        Grade = <span class="hljs-number">56</span>
    }
);
students.Add(
    <span class="hljs-keyword">new</span> Student
    {
        Id = <span class="hljs-number">4</span>,
        Name = <span class="hljs-string">"Dave Brown"</span>,
        Grade = <span class="hljs-number">76</span>
    }
);
<span class="hljs-keyword">foreach</span> (Student student <span class="hljs-keyword">in</span> students)
{
    Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{student.Id}</span> <span class="hljs-subst">{student.Name}</span> <span class="hljs-subst">{student.Grade}</span> "</span>);
}
<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// 1 Dale Jones 60</span>
<span class="hljs-comment">// 2 Gale Davis 89</span>
<span class="hljs-comment">// 3 Debbie Hill 56</span>
<span class="hljs-comment">// 4 Dave Brown 76</span>
</code></pre>
<p>Through generics, you are able to reuse the functionality in the built-in <code>list</code> data type to store multiple types of data. Any generic list used in your C# code must be strongly typed with one particular data type.</p>
<p>You can strongly type the generic list by passing in the relevant type as an argument when defining and instantiating an object of the <code>List</code> type.</p>
<p>Prior to the generic <code>List</code> type being introduced (in .NET Framework 2.0), you could use an <code>ArrayList</code> to store a collection of heterogeneous data types. You could store multiple different data types within one <code>ArrayList</code>.</p>
<p>The problem with the <code>ArrayList</code> is that any calling code retrieving an item from an <code>ArrayList</code> must first convert that value to its appropriate data type before the value can be of any use.</p>
<p>Every item stored in an <code>ArrayList</code> is ‘boxed' within the <code>object</code> type. This is possible because all C# data types inherit from the <code>object</code> data type, so every data type in C# can be implicitly boxed into an object.</p>
<p>Boxing is simply the process of converting a value type to the <code>object</code> type in C#. When the common language runtime (CLR) boxes a value type, it wraps the value inside a <code>System.Object</code> instance and stores it on the managed heap. So in order to use an item retrieved from an <code>ArrayList</code>, the object must first be converted or 'unboxed' into its original type.</p>
<p>This highlights one of the main advantages of using generics in C#. Through using the generic <code>List</code> to store strongly typed items in a collection, you can avoid 'boxing' and 'unboxing'. This means that with generics, the performance overhead caused through 'boxing' and 'unboxing' is also avoided.</p>
<p>The other main advantage is that you can avoid type-related errors that can occur as a result of explicit type conversions needing to be performed on an item retrieved from an <code>ArrayList</code> at runtime.</p>
<p>So by strongly typing a <code>List</code> at compile time, the compiler is able to check that all data type-related code is correct before it is deployed into production. In this way, data type-related errors are preempted at compile time.</p>
<p>Depicted in figure 84, is an example of using an <code>ArrayList</code>  to store heterogeneous data types.</p>
<p>Figure 84.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Collections;
<span class="hljs-keyword">using</span> System.ComponentModel;

ArrayList studentDetails = <span class="hljs-keyword">new</span> ArrayList();
<span class="hljs-keyword">int</span> grade = <span class="hljs-number">90</span>;
<span class="hljs-keyword">string</span> name = <span class="hljs-string">"Bob Jones"</span>;
studentDetails.Add(<span class="hljs-number">90</span>); <span class="hljs-comment">// int value boxed as object</span>
studentDetails.Add(<span class="hljs-string">"Bob Jones"</span>);
studentDetails.Add(
    <span class="hljs-keyword">new</span> Student
    {
        Id = <span class="hljs-number">1</span>,
        Name = <span class="hljs-string">"Bob Jones"</span>,
        Grade = <span class="hljs-number">90</span>
    }
);
grade = Convert.ToInt32(studentDetails[<span class="hljs-number">0</span>]); <span class="hljs-comment">// runtime performance slowed by unboxing int student = int32.Parse(studentDetails[2]); // This would result in a runtime exception being thrown due to an invalid type conversion operation being performed at runtime</span>
</code></pre>
<p>So you can see that using a generic <code>List</code> to store strongly typed values in a collection (rather than an <code>ArrayList</code> where 'boxing' and 'unboxing' code needs to be performed) results in a performance improvement. It also ensures better robustness at runtime.</p>
<p>The example depicted in figure 85 is a more complicated example of using generics in C#. In this example, the factory pattern is employed where you can reuse the <code>GetInstance</code> method to instantiate objects of different types using the same instantiation functionality enveloped in the <code>GetInstance</code> method.</p>
<p>You can see that <code>K</code> and <code>T</code> are used as placeholders to represent the types that can be passed as arguments to the class at compile time (that is, in order to strongly type the class). The <code>where</code> keyword denotes constraints (which are defined rules) on the type arguments passed to this class.</p>
<p>So these constraints mean that the type passed as an argument to the parameter represented by the <code>T</code> placeholder must be a class. The <code>new</code> keyword followed by open and closed brackets denotes that a new object must be created from the relevant class which is of type <code>K</code>.</p>
<p>Figure 85.</p>
<pre><code class="lang-csharp"><span class="hljs-comment">// Instantiation of objects from the generic types passed as objects to the FactoryPattern class.</span>
IStudent student = FactoryPattern&lt;IStudent, Student&gt;.GetInstance();
student.Name = <span class="hljs-string">"Bob Jones"</span>;
student.Grade = <span class="hljs-number">78</span>;
student.Subject = <span class="hljs-string">"Math"</span>;
Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{student.Name}</span> <span class="hljs-subst">{student.Grade}</span> <span class="hljs-subst">{student.Subject}</span>"</span>);
IStudent student2 = FactoryPattern&lt;IStudent, Student&gt;.GetInstance();
student2.Name = <span class="hljs-string">"Debbie Long"</span>;
student2.Grade = <span class="hljs-number">84</span>;
student2.Subject = <span class="hljs-string">"Science"</span>;
Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{student2.Name}</span> <span class="hljs-subst">{student2.Grade}</span> <span class="hljs-subst">{student2.Subject}</span>"</span>);
IProfessor professor = FactoryPattern&lt;IProfessor, Proffessor&gt;.GetInstance();
professor.Name = <span class="hljs-string">"Ron Willis"</span>;
professor.MainSubject = <span class="hljs-string">"Math"</span>;
Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{professor.Name}</span> <span class="hljs-subst">{professor.MainSubject}</span>"</span>);

<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// Bob Jones 78 Math</span>
<span class="hljs-comment">// Debbie Long 84 Science</span>
<span class="hljs-comment">// Ron Willis Math</span>
<span class="hljs-keyword">static</span> <span class="hljs-keyword">class</span> <span class="hljs-title">FactoryPattern</span>&lt;<span class="hljs-title">K</span>, <span class="hljs-title">T</span>&gt;
    <span class="hljs-keyword">where</span> <span class="hljs-title">T</span> : <span class="hljs-keyword">class</span>, <span class="hljs-title">K</span>, <span class="hljs-title">new</span>()
{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> K <span class="hljs-title">GetInstance</span>(<span class="hljs-params"></span>)</span>
    {
        K objK;
        objK = <span class="hljs-keyword">new</span> T();
        <span class="hljs-keyword">return</span> objK;
    }
}
</code></pre>
<p>So in the example depicted in figure 85, generics is used to create clean, reusable code for the implementation of the factory pattern.</p>
<p>A single code block is used to create instances of objects derived from multiple user defined types. Through generics the amount of code is minimised, and if you have a good knowledge of generics, this code is easy to maintain and reuse. Generics gives you greater design flexibility, and ensures better runtime performance and robustness.</p>
<p>For more information on C# Generics and more code examples, you can watch the YouTube video below.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/UUF8QCf3rpI" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>For a full video series on generics in C#, you can go here:</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=UUF8QCf3rpI&amp;list=PL4LFuHwItvKaeSVOur67Lu-0I7sfjf5N3">Full Video Series on C# Generics</a></p>
<h2 id="heading-linq">LINQ</h2>
<p>LINQ stands for Language-Integrated Query and was first introduced to .NET languages with .NET Framework version 3.5 in 2007. It provides .NET developers with a high level query abstraction where, for example, C# code can be used to natively query collections of C# objects. It's similar to the well known relational database management system declarative query language, T-SQL – but the entities being queried with LINQ code are collections of objects rather than rows within database tables.</p>
<p>The code example depicted in figure 86 shows how T-SQL might be used to query a database table named, <code>Employees</code>, in order to bring back all the field values in each row stored in the <code>Employees</code> database table.</p>
<p>Figure 86.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> * <span class="hljs-keyword">FROM</span> Employees
</code></pre>
<p>In figure 87, a code example is depicted where LINQ in C# code is leveraged to query a collection of <code>Employee</code> objects.</p>
<p>Figure 87</p>
<pre><code class="lang-csharp">List&lt;Employee&gt; employees = <span class="hljs-keyword">new</span> List&lt;Employee&gt;();
employees.Add(
    <span class="hljs-keyword">new</span> Employee
    {
        Id = <span class="hljs-number">1</span>,
        FirstName = <span class="hljs-string">"Gavin"</span>,
        LastName = <span class="hljs-string">"Lon"</span>,
        Salary = <span class="hljs-number">10000</span>
    }
);
employees.Add(
    <span class="hljs-keyword">new</span> Employee
    {
        Id = <span class="hljs-number">2</span>,
        FirstName = <span class="hljs-string">"Sandy"</span>,
        LastName = <span class="hljs-string">"James"</span>,
        Salary = <span class="hljs-number">90000</span>
    }
);
employees.Add(
    <span class="hljs-keyword">new</span> Employee
    {
        Id = <span class="hljs-number">3</span>,
        FirstName = <span class="hljs-string">"Greg"</span>,
        LastName = <span class="hljs-string">"Jones"</span>,
        Salary = <span class="hljs-number">73000</span>
    }
);
<span class="hljs-keyword">var</span> employeeResults = <span class="hljs-keyword">from</span> e <span class="hljs-keyword">in</span> employees <span class="hljs-keyword">select</span> e;
<span class="hljs-keyword">foreach</span> (Employee emp <span class="hljs-keyword">in</span> employees)
{
    Console.WriteLine(emp.FirstName);
}
</code></pre>
<p>If for example the <code>Employees</code> database table contained four fields, namely <code>Id</code>, <code>FirstName</code>, <code>LastName</code> and <code>Salary</code>, and you wanted to only bring back the <code>FirstName</code> and <code>LastName</code> fields through your T-SQL query, your query would look like the example in figure 88.</p>
<p>Figure 88.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> FirstName, LastName <span class="hljs-keyword">FROM</span> Employees
</code></pre>
<p>In order to bring back the <code>FirstName</code> and <code>LastName</code> fields from a collection of objects where each object has an <code>Id</code> property, a <code>FirstName</code> property, a <code>LastName</code> property, and a <code>Salary</code> property your LINQ query could be implemented as is shown in the code example in figure 89.</p>
<p>Figure 89.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> employeeResults =
    <span class="hljs-keyword">from</span> e <span class="hljs-keyword">in</span> employees
    <span class="hljs-keyword">select</span> <span class="hljs-keyword">new</span> Employee { FirstName = e.FirstName, LastName = e.LastName };
</code></pre>
<p>There are two types of syntax you can leverage to implement LINQ in C#. The type of syntax you've seen so far in this section is known as query syntax. Another way to implement LINQ code is by using method syntax.</p>
<p>To illustrate the use of query syntax vs method syntax, let's look at a slightly more complex example. In the example depicted in figure 90, a T-SQL query is used to bring back the <code>FirstName</code> and <code>LastName</code> fields, for rows pertaining to employees that have a salary higher than <code>50000</code>.</p>
<p>Figure 90.</p>
<pre><code class="lang-sql"><span class="hljs-keyword">SELECT</span> FirstName, LastName <span class="hljs-keyword">FROM</span> Employees e <span class="hljs-keyword">WHERE</span> e.Salary &gt; <span class="hljs-number">50000</span>
</code></pre>
<p>Using Query syntax in LINQ to perform the equivalent query against a collection of <code>Employee</code> objects, the code would look like what is depicted in figure 91.</p>
<p>Figure 91.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> employeeResults =
    <span class="hljs-keyword">from</span> e <span class="hljs-keyword">in</span> employees
    <span class="hljs-keyword">where</span> e.Salary &gt; <span class="hljs-number">50000</span>
    <span class="hljs-keyword">select</span> <span class="hljs-keyword">new</span> Employee
    {
        FirstName = e.FirstName,
        LastName = e.LastName,
        Salary = e.Salary
    };
</code></pre>
<p>Using method syntax in LINQ, the equivalent query could be implemented with the code depicted in figure 92.</p>
<p>Figure 92.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">var</span> employeeResults = employees
    .Select(e =&gt; <span class="hljs-keyword">new</span> Employee
    {
        FirstName = e.FirstName,
        LastName = e.LastName,
        Salary = e.Salary
    })
    .Where(e =&gt; e.Salary &gt; <span class="hljs-number">50000</span>);
</code></pre>
<p>These LINQ related code examples hopefully give you a sense of how method syntax looks compared to query syntax.</p>
<p>Note that you can't create all LINQ queries using query syntax, so depending on your requirements you may have to use method syntax for performing certain queries using LINQ.</p>
<p>Behind the scenes, the C# compiler converts query syntax to method syntax. Query syntax was introduced in the LINQ technology specifically to improve the readability of your queries.</p>
<p>LINQ is made up of many extension methods that reside within the <code>System.LINQ</code> namespace. In the example in figure 92, the <code>Select</code> and <code>Where</code> LINQ extension methods have been appropriately chained together to create the desired query.</p>
<p>For more detils on LINQ and for more code examples, you can watch the  YouTube video below.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/UfZOmSCCbDY" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>For a full video series on LINQ, you can go here:</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=UfZOmSCCbDY&amp;list=PL4LFuHwItvKbzDl6MBp3XY0MrnALSfyub">Full Video Series on Using LINQ in C#</a></p>
<h2 id="heading-c-attributes">C# Attributes</h2>
<p>You can associate metadata with program entities (for example assemblies, types, methods, and properties) through the use of attributes in C#.</p>
<p>Attributes are powerful when combined with reflection (a concept we'll discuss in the next section). Through the use of reflection, the attributes can be queried at runtime and then custom functionality can be executed based on the metadata provided through the use of the relevant attributes.</p>
<p>Attributes in C# are created as objects at runtime. Their properties and methods can be used just like any other object in C#.</p>
<p>There are two broad categories for attributes: predefined attributes and custom attributes. Predefined attributes are built into the base class libraries provided in .NET, and custom attributes allow you to define your own attributes that address your unique application requirements.</p>
<p>An example of a predefined general attribute is the <code>obsolete</code> attribute. You can check out figure 93 for a code example depicting how you can use the <code>obsolete</code> attribute and how it can be useful when you're attempting to consume an obsolete method (or a method marked as obsolete with the <code>obsolete</code> attribute).</p>
<p>In the code example, you can see that the <code>obsolete</code> attribute decorates a method named <code>LogToScreen</code>. A new updated method named <code>LogToFile</code> has been created within the same class to replace the old <code>LogToScreen</code> method. So the creator of the <code>Logging</code> class would prefer the <code>LogToFile</code> method be consumed by developers (when applying logging functionality in calling code) rather than the <code>LogToScreen</code> method.</p>
<p>When the consumer of the class tries to use the older obsolete method (in this example, the <code>LogToScreen</code> method), a predefined warning message can be displayed to the developer from inside their code editor. This warning message is created to warn developers who wish to consume the logging functionality that the <code>LogToFile</code> method should be used for logging and not the obsolete <code>LogToScreen</code> method.</p>
<p>So to ensure that an appropriate message is displayed, you can pass an appropriate custom message as an argument to the <code>obsolete</code> attribute that appropriately decorates the <code>LogToScreen</code> method (which has now been deemed as obsolete). The warning message can for example warn developers that the old method (<code>LogToScreen</code>) is now obsolete and direct them to use the new preferred method (<code>LogToFile</code>) in its place.</p>
<p>Figure 93.</p>
<pre><code class="lang-csharp">Logging logAction = <span class="hljs-keyword">new</span> Logging();
logAction.LogToScreen(<span class="hljs-string">"Start of Code"</span>); <span class="hljs-comment">// This message, "The LogToScreen method is now obsolete. Please use the LogToFile method instead" is flagged by the C# compilerSomeFunction();</span>
logAction.LogToScreen(<span class="hljs-string">"End of Code"</span>); <span class="hljs-comment">// This message, "The LogToScreen method is now obsolete. Please use the LogToFile method instead" is flagged by the C# compiler</span>
</code></pre>
<p>In the example depicted in figure 94, a custom attribute is created through the implementation of a C# class that inherits from the built-in C# class <code>System.Attribute</code>. A general predefined attribute named, <code>AttributeUsage</code> is used to decorate the class in order to enforce the usage rules associated with the <code>Required</code> custom attribute.</p>
<p>The arguments being passed (in this example) to the <code>AttributeUsage</code> attribute establish the rules where the <code>Required</code> attribute can only be associated with field, parameter, and property program elements, and cannot be applied to the same element multiple times.</p>
<p>The <code>Required</code> attribute can only be applied to a particular program element once, and can be applied to fields, parameters, and properties.</p>
<p>In the example depicted in <strong>figure 94</strong>, a very basic use of a custom attribute is implemented where an custom attribute named <code>RequiredAttribute</code> is used to decorate certain properties of a model. Note that when a custom attribute is actually applied, the 'Attribute' part of the custom attribute's name can be omitted. So in <strong>figure 94</strong> you can see that the relevant program elements are decorated with the attribute named,<code>Required</code> and not <code>RequiredAttribute</code>.</p>
<p>The <code>EmployeeModel</code> model class is used to represent an <code>Employee</code> record. The class named, <code>EmployeeModel</code>, provides a template for an employee record. The <code>Required</code> attribute gives you the ability to reuse this custom attribute across properties where <code>Required</code> validation is necessary (that is, where a user must input a value that is subsequently assigned to the property decorated with the <code>Required</code> attribute).</p>
<p>In the calling code, reflection is employed to inspect the property program elements of the <code>EmployeeModel</code> user defined type at runtime to see if there are any attributes applied to its properties.</p>
<p>In this basic example, the code queries the <code>Id</code> property of the <code>EmployeeModel</code> class, and the <code>Required</code> attribute is found to be associated with the <code>Id</code> property. The code then knows to appropriately validate the user's input for the <code>Id</code> property of the <code>EmployeeModel</code> class.</p>
<p>Note that the <code>Required</code> attribute is also applied to the <code>FirstName</code> property. So you can see how an attribute can be applied multiple times in order to address cross cutting concerns.</p>
<p>Figure 94.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Reflection;

Console.WriteLine(<span class="hljs-string">"Please enter an Id for the employee:"</span>);
<span class="hljs-keyword">string</span> id = Console.ReadLine();
Type employeeType = <span class="hljs-keyword">typeof</span>(EmployeeModel);
PropertyInfo prop = employeeType.GetProperty(<span class="hljs-string">"Id"</span>);
Attribute[] attributes = prop.GetCustomAttributes().ToArray();
<span class="hljs-keyword">foreach</span> (Attribute attr <span class="hljs-keyword">in</span> attributes)
{
    <span class="hljs-keyword">if</span> (attr <span class="hljs-keyword">is</span> RequiredAttribute)
    {
        <span class="hljs-keyword">if</span> (<span class="hljs-keyword">string</span>.IsNullOrEmpty(id))
        {
            Console.WriteLine(
                <span class="hljs-string">"The employee’s Id is required. You did not enter the employee’s Id. "</span>
            );
        }
    }
}

<span class="hljs-keyword">class</span> <span class="hljs-title">EmployeeModel</span>
{
    [<span class="hljs-meta">Required</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> Id { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    [<span class="hljs-meta">Required</span>]
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> FirstName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> LastName { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }
}

[<span class="hljs-meta">AttributeUsage(
    AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property,
    AllowMultiple = false
)</span>]
<span class="hljs-keyword">class</span> <span class="hljs-title">RequiredAttribute</span> : <span class="hljs-title">Attribute</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">string</span> ErrorMessage { <span class="hljs-keyword">get</span>; <span class="hljs-keyword">set</span>; }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">RequiredAttribute</span>(<span class="hljs-params"></span>)</span>
    {
        ErrorMessage = <span class="hljs-string">"You cannot leave field, {0}, empty"</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">RequiredAttribute</span>(<span class="hljs-params"><span class="hljs-keyword">string</span> errorMessage</span>)</span>
    {
        ErrorMessage = errorMessage;
    }
}
</code></pre>
<p>You can check out the following video that contains more details and code examples pertaining to C# Attributes.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/JOM6zDb9Wa8" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-reflection-in-c">Reflection in C</h2>
<p>Reflection is a concept in C#, where the programmer is able to create C# code that can dynamically read the metadata of .NET assemblies at runtime. This gives you a powerful tool where you can create code to dynamically analyse a .NET assembly based on the assembly's metadata at runtime. Your code can for e.g. read the assemblies relevant metadata using Reflection, and output the descriptive metadata about the analysed assembly.</p>
<p>Reflection can even be used to dynamically bind an object to a specific type that resides within the assembly at runtime and execute code that resides within the type’s methods. This is known as late binding.</p>
<p>Most of the time, you won't use reflection to call the code within a .NET assembly and will rather use early binding. Early binding means the C# compiler knows (as it were) about the assemblies' relevant program elements for e.g. an assemblies' classes and public methods at compile time.</p>
<p>Using early binding is the safest way to consume a type’s functionality, because any potential exceptions related to calling code within the early bound object are flagged at compile time. This prevents potentially erroneous code from being released into production, where it can result in runtime errors occurring.</p>
<p>When early binding is used, due to the self-describing nature of .NET assemblies where metadata is stored within the .NET assembly, the C# compiler is able to know (as it were) all the relevant details about the assembly at compile time.</p>
<p>So this metadata stored within .NET assemblies means early binding is possible, where the C# compiler has all the necessary type knowledge, if you like, at compile time.</p>
<p>Using reflection, you are able to use the technique of late binding which occurs at runtime. Late binding can be used to dynamically bind to an object (derived from a type that resides within the relevant assembly) at runtime and consume functionality that resides within the relevant .NET assembly.</p>
<p>This is a powerful tool, but is not a safe way to execute the functionality within a .NET assembly, because late binding means that the calling code learns about the target assembly at runtime by reading its metadata before executing the code within the assembly. The technique of late binding is therefore more prone to runtime errors, as potential errors cannot be dealt with at compile time – that is, before the code within the assembly is executed at runtime.</p>
<p>In the example depicted in figure 96, code within an assembly is dynamically invoked using reflection and late binding.</p>
<p>Figure 95.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System;
<span class="hljs-keyword">using</span> System.Collections.Generic;
<span class="hljs-keyword">using</span> System.Text;

<span class="hljs-keyword">namespace</span> <span class="hljs-title">UtilityFunctions</span>
{
    <span class="hljs-keyword">public</span> <span class="hljs-keyword">class</span> <span class="hljs-title">BasicMathFunctions</span>
    {
        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">DivideOperation</span>(<span class="hljs-params"><span class="hljs-keyword">double</span> number1, <span class="hljs-keyword">double</span> number2</span>)</span>
        {
            <span class="hljs-keyword">return</span> number1 / number2;
        }

        <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">MultiplyOperation</span>(<span class="hljs-params"><span class="hljs-keyword">double</span> number1, <span class="hljs-keyword">double</span> number2</span>)</span>
        {
            <span class="hljs-keyword">return</span> number1 * number2;
        }
    }
}
</code></pre>
<p>A code example is depicted in figure 96, where the code resides within a different assembly to the assembly that contains the <code>BasicMathFunctions</code> type depicted in figure 95.</p>
<p>In the calling code (depicted in figure 96), reflection is used to late bind to the <code>BasicMathFunctions</code> type and call the <code>MultiplyOperation</code> method. So the code depicted in figure 95 resides within an assembly denoted by a file named "UtilityFunctions.dll".</p>
<p>The "UtilityFunction.dll" assembly resides within the same directory as the assembly that contains the calling code (depicted in figure 96). Reflection is used to dynamically load the "UtilityFunctions" assembly, late bind to the <code>BasicMathFunctions</code> type, and call its <code>MultiplyOperation</code> method.</p>
<p>Figure 96.</p>
<pre><code class="lang-csharp"><span class="hljs-keyword">using</span> System.Reflection;

<span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> TargetAssemblyFileName = <span class="hljs-string">"UtilityFunctions.dll"</span>;
<span class="hljs-keyword">const</span> <span class="hljs-keyword">string</span> TargetNamespace = <span class="hljs-string">"UtilityFunctions"</span>;
Assembly assembly = Assembly.LoadFile(
    Path.Combine(AppDomain.CurrentDomain.BaseDirectory, TargetAssemblyFileName)
);
Type classType = assembly.GetType(<span class="hljs-string">"UtilityFunctions.BasicMathFunctions"</span>);
<span class="hljs-keyword">object</span> classInstance = Activator.CreateInstance(classType);
MethodInfo method = classType.GetMethod(<span class="hljs-string">"MultiplyOperation"</span>);
<span class="hljs-keyword">object</span>[] paramValues = <span class="hljs-keyword">new</span> <span class="hljs-keyword">object</span>[<span class="hljs-number">2</span>];
paramValues[<span class="hljs-number">0</span>] = <span class="hljs-number">2</span>;
paramValues[<span class="hljs-number">1</span>] = <span class="hljs-number">3</span>;
<span class="hljs-keyword">object</span> result = method.Invoke(classInstance, paramValues);
Console.WriteLine(<span class="hljs-string">$"<span class="hljs-subst">{paramValues[<span class="hljs-number">0</span>]}</span> * <span class="hljs-subst">{paramValues[<span class="hljs-number">1</span>]}</span>  = <span class="hljs-subst">{result}</span>"</span>);
<span class="hljs-comment">// Output:</span>
<span class="hljs-comment">// 2 * 3  = 6</span>
</code></pre>
<p>For more details and code examples pertaining to reflection, you can watch the YouTube video below.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/tGMa9qjncjs" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-video-on-asynchronous-programming-in-c">Video on Asynchronous Programming in C</h2>
<p>I haven't covered Asynchronous programming in this C# book. But if you'd like to learn about Asynchronous programming in C#, you can watch the YouTube video below.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/MyblIAk8cNI" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<p>For a full video series on asynchronous programming in C#, check this out:</p>
<p><a target="_blank" href="https://www.youtube.com/watch?v=MyblIAk8cNI&amp;list=PL4LFuHwItvKb5A9W1myICdC-GJU4_6cKE">Full Video Series on Asynchronous Programming in C#</a></p>
<p>If you'd like to learn about how to create sophisticated web applications using C#, I've provided some resources below.</p>
<p>The first link takes you do a YouTube video playlist that provides step by step instructions on how to build a Shopping Cart SPA (Single Page Application) using the Blazor framework. The second link takes you to a YouTube video playlist that provides step by step instructions on how to build a real-word web application using the ASP .NET Core MVC framework.</p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=3_AsedRrqww&amp;list=PL4LFuHwItvKbdK-ogNsOx2X58hHGeQm8c">Full Blazor Shopping Cart SPA (Single Page Application) Course</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=D7R_ToqDKHg&amp;list=PL4LFuHwItvKZ6Mz5W5wzD9uo3w6tNChhX">Full ASP .Net CORE MVC Course</a></li>
</ul>
<h2 id="heading-conclusion">Conclusion</h2>
<p>The goal of this book is to help you gain an understanding of the powerful features available in the C# programming language. The code examples were designed to provide you with a practical knowledge of these features.</p>
<p>You can apply these code examples yourself using free tools like Visual Studio 2022 Community edition or Visual Studio Code in order to gain hands-on experience working with the concepts discussed in this book.</p>
<p>I have worked with C# for over two decades and have been impressed with the evolution of the language itself as well as the environment in which C# code runs, namely .NET. When you master C#, a whole world of creativity, intellectually challenging concepts, and a multitude of career opportunities will open up to you.</p>
<p>In today’s world, you have the benefit of development tools as well as instructions on how to use those development tools freely available to you. There is also a lot of free content available online on how to use the C# programming language in order to create real-world applications.</p>
<p>Using C#, you can create a large variety of different types of applications. You can create cross platform desktop applications, cross platform mobile applications, a variety of types of web applications like SPAs that leverage the Blazor framework. You can create sophisticated 2D and 3D games. You can create IoT applications. You can create globally distributed cloud native applications that leverage the Micro-service architecture.</p>
<p>You are almost unlimited in terms of the types of applications you can create for a multitude of types of platforms and devices. With C# you can easily integrate AI into your applications as well.</p>
<p>It is a very exciting time to be a C# and .NET developer. I wish you the very best with learning and leveraging this powerful programming language on your journey as a developer!</p>
<p>For a full course for C# beginners and a full Advanced C# course, check out these resources:</p>
<ul>
<li><a target="_blank" href="https://www.youtube.com/watch?v=2pquQMSYk6c&amp;list=PL4LFuHwItvKbneXxSutjeyz6i1w32K6di">Full C# for Beginners Course</a></li>
<li><a target="_blank" href="https://www.youtube.com/watch?v=3cfVmcAkR2w&amp;list=PL4LFuHwItvKaOi-bN1E2WUVyZbuRhVokL">Full Advanced C#  Course</a></li>
</ul>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Advanced Object-Oriented Programming in Java – Full Book ]]>
                </title>
                <description>
                    <![CDATA[ Java is a go-to language for many programmers, and it's a critical skill for any software engineer. After learning Java, picking up other programming languages and advanced concepts becomes much easier.  In this book, I'll cover the practical knowled... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/object-oriented-programming-in-java/</link>
                <guid isPermaLink="false">66b99b074ed1a5964b770077</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Object Oriented Programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Vahe Aslanyan ]]>
                </dc:creator>
                <pubDate>Tue, 16 Jan 2024 23:17:07 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2024/01/Advanced-Object-Oriented-Programming-in-Java-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Java is a go-to language for many programmers, and it's a critical skill for any software engineer. After learning Java, picking up other programming languages and advanced concepts becomes much easier. </p>
<p>In this book, I'll cover the practical knowledge you need to move from writing basic Java code to designing and building resilient software systems.</p>
<p>Many top companies rely on Java, so understanding it is essential, not just for tech jobs but also if you're considering starting your own business. </p>
<p>Looking to move up in your career? Contributing to open-source projects can be a smart move. This guide will also help you with the advanced skills you'll need to become an open-source Java developer and get noticed by employers.</p>
<p>And finally, the book will help you stay current with the latest in technology as you learn about the Java behind AI, big data, and cloud computing. You'll learn to create high-performance Java applications that are fast, efficient, and reliable.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>Before diving into the advanced concepts covered in this book, it is essential to have a solid foundation in Java fundamentals and Object-Oriented Programming (OOP). </p>
<p>This guide builds upon the knowledge and skills acquired in my previous book <a target="_blank" href="https://www.freecodecamp.org/news/learn-java-object-oriented-programming/">Learn Java Fundamentals – Object-Oriented Programming</a>. </p>
<p>Here are the key prerequisites:</p>
<h3 id="heading-strong-understanding-of-java-basics">Strong Understanding of Java Basics</h3>
<ul>
<li><strong>Syntax and Structure</strong>: Familiarity with Java syntax and basic programming constructs.</li>
<li><strong>Basic Programming Concepts</strong>: Proficiency in writing and understanding simple Java programs.</li>
</ul>
<h3 id="heading-proficiency-in-object-oriented-programming-concepts">Proficiency in Object-Oriented Programming Concepts</h3>
<ul>
<li><strong>Classes and Objects</strong>: Deep understanding of classes, objects, and their interactions.</li>
<li><strong>Inheritance and Polymorphism</strong>: Knowledge of how inheritance and polymorphism are implemented in Java.</li>
<li><strong>Encapsulation and Abstraction</strong>: Ability to encapsulate data and utilize abstraction in program design.</li>
</ul>
<h3 id="heading-experience-with-java-data-types-and-operators">Experience with Java Data Types and Operators</h3>
<ul>
<li><strong>Primitive and Non-primitive Data Types</strong>: Comfort with using various data types in Java.</li>
<li><strong>Operators</strong>: Familiarity with arithmetic, relational, and logical operators.</li>
</ul>
<h3 id="heading-control-structures-and-error-handling">Control Structures and Error Handling</h3>
<ul>
<li><strong>Control Flow Statements</strong>: Proficiency in using <code>if</code>, <code>else</code>, <code>switch</code>, and loop constructs.</li>
<li><strong>Exception Handling</strong>: Basic understanding of handling exceptions in Java.</li>
</ul>
<h3 id="heading-basic-understanding-of-java-apis-and-libraries">Basic Understanding of Java APIs and Libraries</h3>
<ul>
<li>Familiarity with using standard Java libraries and APIs for common tasks.</li>
</ul>
<p>This guide assumes that you have already mastered these fundamental concepts and are ready to explore more advanced topics in Java programming. </p>
<p>This book will delve into complex topics that require a strong foundation in basic OOP principles, along with familiarity with Java's core features and functionalities.</p>
<h2 id="heading-how-this-book-will-help-you">How this Book Will Help You:</h2>
<ol>
<li>Position yourself as a top candidate for senior Java developer roles, ready to tackle high-stakes projects and lead innovative software development initiatives.</li>
<li>Transform you into an expert in high-demand areas such as concurrency and network programming, making you an invaluable asset to any team.</li>
<li>Build a portfolio of impressive projects, from dynamic web applications to sophisticated mobile games, showcasing your advanced Java skills to potential employers.</li>
<li>Learn to write code that's not only functional but exceptionally clean and efficient, adhering to the best practices that define expert-level Java programming.</li>
<li>Engage with a community of like-minded developers, and by the end of this guide, you’ll not only gain knowledge but also a network of peers to collaborate with on future Java endeavors.</li>
<li>Equip yourself with advanced problem-solving skills that enable you to dissect and overcome real-world software development challenges with innovative solutions.</li>
<li>Stay ahead of the curve by mastering the latest Java features and frameworks that will define the future of software development.</li>
<li>Prepare yourself to achieve Java certification, validating your skills and knowledge in a way that's recognized across the industry.</li>
<li>Gain the confidence to contribute to open-source projects or even start your own, with the deep understanding of Java that this guide provides.</li>
</ol>
<p>You're embarking on a journey to master Java Object-Oriented Programming, a skill that paves the way for diverse opportunities in software engineering. This guide will lay a foundation for you to transition from writing code to building robust software systems. </p>
<p>With these advanced skills, you're poised to contribute to open-source projects, qualify for top Java developer roles, and stay ahead in the tech industry. Your path from learning to leading in the Java community starts here. Let's begin.</p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-chapter-1-unit-testing-and-debugging">Chapter 1: Unit Testing and Debugging</a> </li>
<li><a class="post-section-overview" href="#heading-chapter-2-file-handling-and-inputoutput-io">Chapter 2. File Handling and Input/Output (I/O)</a></li>
<li><a class="post-section-overview" href="#heading-chapter-3-deadlocks-and-how-to-avoid-them">Chapter 3: Deadlocks and How to Avoid Them</a></li>
<li><a class="post-section-overview" href="#heading-chapter-4-java-design-patterns">Chapter 4: Java Design Patterns</a></li>
<li><a class="post-section-overview" href="#heading-chapter-5-how-to-optimize-java-code-for-speed-and-efficiency">Chapter 5: How to Optimize Java Code for Speed and Efficiency</a></li>
<li><a class="post-section-overview" href="#heading-chapter-6-concurrent-data-structures-and-algorithms-for-high-performance-applications">Chapter 6: Concurrent Data Structures and Algorithms</a></li>
<li><a class="post-section-overview" href="#heading-chapter-7-fundamentals-of-java-security">Chapter 7: Fundamentals of Java Security</a></li>
<li><a class="post-section-overview" href="#heading-chapter-8-secure-communication-in-java">Chapter 8: Secure Communication in Java</a></li>
<li><a class="post-section-overview" href="#heading-conclusion">Conclusion</a></li>
</ol>
<h2 id="heading-chapter-1-unit-testing-and-debugging">Chapter 1: Unit Testing and Debugging</h2>
<p>In software development, unit testing and debugging play a vital role in ensuring the quality and reliability of your code. These practices provide a reliable means to verify the correctness of your code, allowing you to identify and address errors or bugs that may hinder its intended functionality. </p>
<p>Unit testing allows you to systematically test individual units of your code, such as functions or methods, applying pressure through tests to ensure their proper functioning. </p>
<p>By conducting these tests, you can establish a reliable method to validate the behavior of your code. This not only instills confidence in your work but also allows you to catch and address potential issues early on, making the development process more efficient.</p>
<p>To become an efficient software engineer, it is crucial to prioritize unit testing and debugging as integral parts of your software development workflow. By doing so, you can ensure the stability and effectiveness of your codebase, providing practical advice that will help you deliver high-quality software.</p>
<h3 id="heading-fundamentals-of-unit-testing">Fundamentals of Unit Testing</h3>
<p>Java, with its rich ecosystem and extensive support for testing frameworks, offers a fertile ground for implementing unit testing practices. In this section, you'll learn about Java's testing landscape, highlighting essential tools and frameworks like JUnit. </p>
<p>JUnit is a widely used testing framework that provides a comprehensive set of features and functionalities to facilitate the creation and execution of high-quality unit tests in Java. </p>
<p>By leveraging tools like JUnit, you can confirm the effectiveness and efficiency of your testing efforts, leading to the development of robust and reliable Java applications.</p>
<p>Examples for unit testing include isolation, repeatability, and simplicity. When conducting unit tests, it is important to focus on testing the beginning, middle, and end of your functions. </p>
<p>By separating each key area and stress testing it, you can ensure thorough testing of your code. This approach aligns with the principles of the scientific method, where you aim to test all crucial aspects of your functions to achieve reliable and accurate results.</p>
<h3 id="heading-unit-testing-examples">Unit Testing Examples</h3>
<p>To illustrate unit testing in Java using JUnit, let's create some practical examples. We'll focus on a simple Java class and how we can apply unit testing to it, adhering to principles like isolation, repeatability, and simplicity.</p>
<p>Suppose we have a Java class named <code>Calculator</code> with a couple of basic mathematical operations:</p>
<pre><code class="lang-jsx">public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span> </span>{

    public int add(int a, int b) {
        <span class="hljs-keyword">return</span> a + b;
    }

    public int subtract(int a, int b) {
        <span class="hljs-keyword">return</span> a - b;
    }

    <span class="hljs-comment">// Additional methods for multiplication and division can be added here.</span>
}
</code></pre>
<p>Using JUnit, we will write test cases that individually test each method of the <code>Calculator</code> class.</p>
<p>First, include JUnit in your project. If you're using Maven, add the following dependency to your <strong><code>pom.xml</code></strong>:</p>
<pre><code class="lang-jsx"> &lt;dependency&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">groupId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">groupId</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">artifactId</span>&gt;</span>junit<span class="hljs-tag">&lt;/<span class="hljs-name">artifactId</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">version</span>&gt;</span>4.13.2<span class="hljs-tag">&lt;/<span class="hljs-name">version</span>&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">scope</span>&gt;</span>test<span class="hljs-tag">&lt;/<span class="hljs-name">scope</span>&gt;</span></span>
&lt;/dependency&gt;
</code></pre>
<p>Now, let's create test cases:</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> org.junit.Assert;
<span class="hljs-keyword">import</span> org.junit.Test;

public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CalculatorTest</span> </span>{

    @Test
    public <span class="hljs-keyword">void</span> testAdd() {
        Calculator calc = <span class="hljs-keyword">new</span> Calculator();
        int result = calc.add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>);
        Assert.assertEquals(<span class="hljs-number">8</span>, result);
    }

    @Test
    public <span class="hljs-keyword">void</span> testSubtract() {
        Calculator calc = <span class="hljs-keyword">new</span> Calculator();
        int result = calc.subtract(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>);
        Assert.assertEquals(<span class="hljs-number">2</span>, result);
    }

    <span class="hljs-comment">// Additional test methods for multiplication and division can be added here.</span>
}
</code></pre>
<p>In these test cases, we follow the principles of unit testing:</p>
<ol>
<li><strong>Isolation</strong>: Each test method (<code>testAdd</code> and <code>testSubtract</code>) is independent of others. They test specific functionalities of the <code>Calculator</code> class. This is what you want to do, test each case systematically and separately.</li>
<li><strong>Repeatability</strong>: These tests can be run multiple times, and they will produce the same results, ensuring consistent behavior of the methods being tested.</li>
<li><strong>Simplicity</strong>: The tests are straightforward and focused solely on the method they are meant to test. For instance, <code>testAdd</code> only tests the <code>add</code> method.</li>
</ol>
<h3 id="heading-how-to-write-helpful-unit-tests">How to Write Helpful Unit Tests</h3>
<p>When crafting unit tests, it's essential to approach them with a clear and systematic strategy. This involves following certain guidelines and asking pertinent questions to ensure comprehensive and effective testing. </p>
<p>Here’s an outline to guide you through the process:</p>
<h4 id="heading-create-a-new-object">Create a New Object</h4>
<p>Firstly, for each test, create a new instance of the object you're testing. This ensures that each test is independent and unaffected by the state changes caused by other tests. In Java, this typically looks like this:</p>
<pre><code class="lang-jsx">@Test
public <span class="hljs-keyword">void</span> testSomeMethod() {
    MyClass objectUnderTest = <span class="hljs-keyword">new</span> MyClass();
    <span class="hljs-comment">// Further test steps follow...</span>
}
</code></pre>
<h4 id="heading-use-assertions">Use Assertions:</h4>
<p>Utilize JUnit's assertion methods like <code>assertEquals</code>, <code>assertTrue</code>, and so on to verify the outcomes of your test. These assertions form the crux of your test, as they validate whether the object's behavior matches expectations. For example:</p>
<pre><code class="lang-jsx">@Test
public <span class="hljs-keyword">void</span> testAddition() {
    Calculator calc = <span class="hljs-keyword">new</span> Calculator();
    int expectedResult = <span class="hljs-number">10</span>;
    int actualResult = calc.add(<span class="hljs-number">7</span>, <span class="hljs-number">3</span>);
    Assert.assertEquals(<span class="hljs-string">"Check if the addition method returns the correct sum"</span>, expectedResult, actualResult);
}
</code></pre>
<h4 id="heading-initiate-several-objects">Initiate Several Objects:</h4>
<p>In some cases, it may be necessary to initiate several objects to simulate more complex interactions. This is particularly useful when testing how different components of your application interact with each other. For instance:</p>
<pre><code class="lang-jsx">@Test
public <span class="hljs-keyword">void</span> testUserTransaction() {
    Account sender = <span class="hljs-keyword">new</span> Account(<span class="hljs-number">1000</span>); <span class="hljs-comment">// Initial balance 1000</span>
    Account receiver = <span class="hljs-keyword">new</span> Account(<span class="hljs-number">500</span>); <span class="hljs-comment">// Initial balance 500</span>
    Transaction transaction = <span class="hljs-keyword">new</span> Transaction();
    transaction.transfer(sender, receiver, <span class="hljs-number">200</span>);
    Assert.assertEquals(<span class="hljs-number">800</span>, sender.getBalance());
    Assert.assertEquals(<span class="hljs-number">700</span>, receiver.getBalance());
}
</code></pre>
<h3 id="heading-key-guidelines-and-questions-for-writing-tests">Key Guidelines and Questions for Writing Tests</h3>
<ol>
<li><strong>What is the expected outcome?</strong> Clearly define what result you expect from the method you're testing. This guides your assertion statements.</li>
<li><strong>Are the tests independent?</strong> Ensure each test can run independently of the others, without relying on shared states or data.</li>
<li><strong>Are edge cases covered?</strong> Include tests for boundary conditions and edge cases, not just the typical or average scenarios. This is key for creating reliable software.</li>
<li><strong>Is each test simple and focused?</strong> Aim for simplicity. Each test should ideally check one aspect or behavior of your method.</li>
<li><strong>How does the method behave under different inputs?</strong> Test a variety of inputs, including valid, invalid, and edge cases, to ensure your method handles them correctly.</li>
<li><strong>Is the test repeatable and consistent?</strong> Your tests should produce the same results every time they're run, under the same conditions.</li>
<li><strong>Are the test names descriptive?</strong> Name your tests clearly to indicate what they are testing. For example, <code>testEmptyListReturnsZero()</code> is more informative than <code>testList()</code>.</li>
<li><strong>Are you checking for exceptions?</strong> Where applicable, write tests to check that your method throws the expected exceptions under certain conditions.</li>
</ol>
<p>Following these guidelines ensures that your unit tests are robust, reliable, and provide a comprehensive assessment of your code's functionality.</p>
<h3 id="heading-practical-unit-testing-scenarios-and-case-studies">Practical Unit Testing Scenarios and Case Studies</h3>
<p>Here are examples of Java code snippets that demonstrate real-world scenarios and case studies related to array manipulation, along with the corresponding unit tests using JUnit. These examples illustrate common challenges and how to address them through effective unit testing and debugging.</p>
<h4 id="heading-sort-a-list-of-products">Sort a List of Products</h4>
<p><strong>Scenario</strong>: A Java method sorts an array of <code>Product</code> objects based on their price.</p>
<p>Product Class:</p>
<pre><code class="lang-jsx"><span class="hljs-comment">// Define a class named 'Product' representing a product with a name and price</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Product</span> </span>{
    <span class="hljs-comment">// Private instance variable 'name' to hold the name of the product</span>
    private <span class="hljs-built_in">String</span> name;

    <span class="hljs-comment">// Private instance variable 'price' to hold the price of the product</span>
    private double price;

    <span class="hljs-comment">// Constructor to initialize a new Product object with a name and price</span>
    public Product(<span class="hljs-built_in">String</span> name, double price) {
        <span class="hljs-built_in">this</span>.name = name; <span class="hljs-comment">// Assign the 'name' argument to the 'name' instance variable</span>
        <span class="hljs-built_in">this</span>.price = price; <span class="hljs-comment">// Assign the 'price' argument to the 'price' instance variable</span>
    }

    <span class="hljs-comment">// Public method 'getName' to return the name of the product</span>
    public <span class="hljs-built_in">String</span> getName() {
        <span class="hljs-keyword">return</span> name; <span class="hljs-comment">// Return the value of the 'name' instance variable</span>
    }

    <span class="hljs-comment">// Public method 'getPrice' to return the price of the product</span>
    public double getPrice() {
        <span class="hljs-keyword">return</span> price; <span class="hljs-comment">// Return the value of the 'price' instance variable</span>
    }
}
</code></pre>
<p>Sorting Method:</p>
<pre><code><span class="hljs-keyword">import</span> java.util.Arrays;

public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductSorter</span> </span>{

    <span class="hljs-comment">// This static method sorts an array of Product objects by their price in ascending order.</span>
    public <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> sortByPrice(Product[] products) {
        <span class="hljs-comment">// Use Arrays.sort method with a lambda expression to define the sorting criteria.</span>
        Arrays.sort(products, (p1, p2) -&gt; Double.compare(p1.getPrice(), p2.getPrice()));
        <span class="hljs-comment">// The lambda expression compares two Product objects based on their price.</span>

        <span class="hljs-comment">// The sort method modifies the 'products' array in place, sorting the Product objects by their price.</span>
        <span class="hljs-comment">// 'p1.getPrice()' and 'p2.getPrice()' fetch the prices of two Product objects for comparison.</span>
        <span class="hljs-comment">// 'Double.compare()' compares two double values and returns an integer to determine the order.</span>
    }
}
</code></pre><p>Unit Test:</p>
<pre><code><span class="hljs-comment">// Import the necessary classes for testing</span>
<span class="hljs-keyword">import</span> org.junit.Assert;
<span class="hljs-keyword">import</span> org.junit.Test;

<span class="hljs-comment">// Create a test class for the ProductSorter class</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProductSorterTest</span> </span>{

    <span class="hljs-comment">// Define a test method to test the sorting of products by price</span>
    @Test
    public <span class="hljs-keyword">void</span> testSortByPrice() {
        <span class="hljs-comment">// Create an array of Product objects with names and prices</span>
        Product[] products = <span class="hljs-keyword">new</span> Product[] {
            <span class="hljs-keyword">new</span> Product(<span class="hljs-string">"Laptop"</span>, <span class="hljs-number">1200.00</span>),
            <span class="hljs-keyword">new</span> Product(<span class="hljs-string">"Phone"</span>, <span class="hljs-number">800.00</span>),
            <span class="hljs-keyword">new</span> Product(<span class="hljs-string">"Watch"</span>, <span class="hljs-number">300.00</span>)
        };

        <span class="hljs-comment">// Call the sortByPrice method to sort the products by price</span>
        ProductSorter.sortByPrice(products);

        <span class="hljs-comment">// Assert that the first product in the sorted array has the name "Watch"</span>
        Assert.assertEquals(<span class="hljs-string">"Watch"</span>, products[<span class="hljs-number">0</span>].getName());

        <span class="hljs-comment">// Assert that the second product in the sorted array has the name "Phone"</span>
        Assert.assertEquals(<span class="hljs-string">"Phone"</span>, products[<span class="hljs-number">1</span>].getName());

        <span class="hljs-comment">// Assert that the third product in the sorted array has the name "Laptop"</span>
        Assert.assertEquals(<span class="hljs-string">"Laptop"</span>, products[<span class="hljs-number">2</span>].getName());
    }
}
</code></pre><h4 id="heading-find-the-maximum-value-in-an-array">Find the Maximum Value in an Array</h4>
<p><strong>Scenario</strong>: A method is supposed to find the maximum value in an array, but it's returning incorrect results.</p>
<p>Method with Bug:</p>
<pre><code><span class="hljs-comment">// Class to perform operations on arrays</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayOperations</span> </span>{
    <span class="hljs-comment">// Method to find the maximum value in an array</span>
    public <span class="hljs-keyword">static</span> int findMax(int[] array) {
        <span class="hljs-comment">// Initialize max with the smallest possible integer value</span>
        int max = Integer.MIN_VALUE;

        <span class="hljs-comment">// Loop through each element in the array</span>
        <span class="hljs-keyword">for</span> (int i = <span class="hljs-number">0</span>; i &lt; array.length; i++) {
            <span class="hljs-comment">// Check if the current element is greater than the current max</span>
            <span class="hljs-keyword">if</span> (array[i] &gt; max) {
                <span class="hljs-comment">// If so, update the max with the new value</span>
                max = array[i];
            }
        }

        <span class="hljs-comment">// Return the maximum value found in the array</span>
        <span class="hljs-keyword">return</span> max;
    }
}
</code></pre><p>Unit Test:</p>
<pre><code><span class="hljs-comment">// Import the necessary classes for testing</span>
<span class="hljs-keyword">import</span> org.junit.Assert;
<span class="hljs-keyword">import</span> org.junit.Test;

<span class="hljs-comment">// Define a test class for ArrayOperations</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayOperationsTest</span> </span>{
    <span class="hljs-comment">// Define a test method for the findMax method in ArrayOperations</span>
    @Test
    public <span class="hljs-keyword">void</span> testFindMax() {
        <span class="hljs-comment">// Define an array to test the findMax method</span>
        int[] array = {<span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">9</span>, <span class="hljs-number">1</span>, <span class="hljs-number">6</span>};
        <span class="hljs-comment">// Call the findMax method with the test array and store the result</span>
        int result = ArrayOperations.findMax(array);
        <span class="hljs-comment">// Assert that the result is as expected (9 in this case)</span>
        Assert.assertEquals(<span class="hljs-number">9</span>, result); <span class="hljs-comment">// This assertion will pass if the findMax method is correct</span>
    }
}
</code></pre><p>Debugging and Fixing: </p>
<p>The issue is in the for-loop, which incorrectly starts from index 1 instead of 0. Correcting the loop to start from index 0 fixes the bug.  </p>
<p>Corrected Method:</p>
<pre><code><span class="hljs-comment">// Class to perform operations on arrays</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayOperations</span> </span>{
    <span class="hljs-comment">// Method to find the maximum value in an array</span>
    public <span class="hljs-keyword">static</span> int findMax(int[] array) {
        <span class="hljs-comment">// Initialize max with the smallest possible integer value</span>
        int max = Integer.MIN_VALUE;

        <span class="hljs-comment">// Loop through each element in the array</span>
        <span class="hljs-keyword">for</span> (int i = <span class="hljs-number">0</span>; i &lt; array.length; i++) {
            <span class="hljs-comment">// Check if the current element is greater than the current max</span>
            <span class="hljs-keyword">if</span> (array[i] &gt; max) {
                <span class="hljs-comment">// If so, update the max with the new value</span>
                max = array[i];
            }
        }

        <span class="hljs-comment">// Return the maximum value found in the array</span>
        <span class="hljs-keyword">return</span> max;
    }
}
</code></pre><p>These examples show how unit testing can reveal bugs in real-world scenarios and guide developers in debugging and fixing issues related to array manipulation in Java.</p>
<h3 id="heading-unit-testing-best-practices">Unit Testing Best Practices</h3>
<p>When it comes to writing and maintaining unit tests in Java, there are several best practices that can help ensure the effectiveness and reliability of your tests.</p>
<p>First and foremost, it is crucial to focus on test isolation. Each unit test should be independent of others, meaning that they should test specific functionalities of the code in isolation. This allows for a more systematic and targeted approach to testing, making it easier to identify and fix any issues that may arise. </p>
<p>By keeping tests isolated, you can ensure that changes made to one test do not inadvertently affect the results of other tests.</p>
<pre><code><span class="hljs-comment">// Import the necessary classes for testing</span>
<span class="hljs-keyword">import</span> org.junit.Assert;
<span class="hljs-keyword">import</span> org.junit.Test;

<span class="hljs-comment">// Define a test class for Calculator</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CalculatorTest</span> </span>{
    <span class="hljs-comment">// Define a test method for the add method in Calculator</span>
    @Test
    public <span class="hljs-keyword">void</span> testAddition() {
        <span class="hljs-comment">// Create a new Calculator object</span>
        Calculator calc = <span class="hljs-keyword">new</span> Calculator();
        <span class="hljs-comment">// Assert that the add method returns the correct result</span>
        Assert.assertEquals(<span class="hljs-number">5</span>, calc.add(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>));
    }

    <span class="hljs-comment">// Define a test method for the subtract method in Calculator</span>
    @Test
    public <span class="hljs-keyword">void</span> testSubtraction() {
        <span class="hljs-comment">// Create a new Calculator object</span>
        Calculator calc = <span class="hljs-keyword">new</span> Calculator();
        <span class="hljs-comment">// Assert that the subtract method returns the correct result</span>
        Assert.assertEquals(<span class="hljs-number">1</span>, calc.subtract(<span class="hljs-number">4</span>, <span class="hljs-number">3</span>));
    }
}
</code></pre><p>Another important best practice is to prioritize test repeatability. Tests should be designed in such a way that they can be run multiple times, producing the same results each time. </p>
<p>This ensures consistent behavior and allows for easy identification of any changes or regressions in the code. By making tests repeatable, you can have confidence in the stability and reliability of your codebase.</p>
<pre><code>public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StringFormatterTest</span> </span>{
    @Test
    public <span class="hljs-keyword">void</span> testUpperCaseConversion() {
        StringFormatter formatter = <span class="hljs-keyword">new</span> StringFormatter();
        Assert.assertEquals(<span class="hljs-string">"HELLO"</span>, formatter.toUpperCase(<span class="hljs-string">"hello"</span>));
    }
}
</code></pre><p>Simplicity is also key when it comes to writing unit tests. Each test should be focused solely on the method or functionality it is meant to test. </p>
<p>By keeping tests simple and concise, you can improve readability and maintainability. Additionally, simple tests are easier to understand and debug, making it quicker to identify and fix any issues that may arise.</p>
<pre><code>public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayUtilsTest</span> </span>{
    @Test
    public <span class="hljs-keyword">void</span> testFindMaximum() {
        int[] numbers = {<span class="hljs-number">1</span>, <span class="hljs-number">3</span>, <span class="hljs-number">5</span>, <span class="hljs-number">7</span>};
        Assert.assertEquals(<span class="hljs-number">7</span>, ArrayUtils.findMaximum(numbers));
    }
}
</code></pre><p>When writing unit tests, it is important to consider edge cases and boundary conditions. These are scenarios that may not be covered by typical or average test cases. </p>
<p>By including tests for edge cases, you can ensure that your code handles these situations correctly and avoid potential bugs or errors. Testing these extreme scenarios is crucial for creating reliable and robust software.</p>
<pre><code>public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayUtilsTest</span> </span>{
    @Test(expected = IllegalArgumentException.class)
    public <span class="hljs-keyword">void</span> testMaximumWithEmptyArray() {
        ArrayUtils.findMaximum(<span class="hljs-keyword">new</span> int[]{});
    }
}
</code></pre><p>Test names should be descriptive and indicative of what is being tested. This helps improve the readability and understandability of the tests, making it easier for other developers to navigate and interpret them. </p>
<p>Clear and concise test names also serve as documentation for the behavior and functionality being tested.</p>
<pre><code>public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PasswordValidatorTest</span> </span>{
    @Test
    public <span class="hljs-keyword">void</span> testPasswordLengthValidity() {
        Assert.assertTrue(PasswordValidator.isValidLength(<span class="hljs-string">"secure123"</span>));
    }

    @Test
    public <span class="hljs-keyword">void</span> testPasswordSpecialCharPresence() {
        Assert.assertFalse(PasswordValidator.containsSpecialCharacter(<span class="hljs-string">"password"</span>));
    }
}
</code></pre><p>In addition to these best practices, it is essential to follow a systematic and comprehensive approach to unit testing. This involves asking pertinent questions and following guidelines to ensure comprehensive and effective testing. </p>
<p>Questions such as "What is the expected outcome?" and "Are the tests independent?" help guide the creation of thorough and reliable unit tests.</p>
<pre><code>public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserAuthenticationTest</span> </span>{
    @Test
    public <span class="hljs-keyword">void</span> testValidUserLogin() {
        User user = <span class="hljs-keyword">new</span> User(<span class="hljs-string">"username"</span>, <span class="hljs-string">"password"</span>);
        Authentication auth = <span class="hljs-keyword">new</span> Authentication();
        Assert.assertTrue(auth.isValidLogin(user));
    }

    <span class="hljs-comment">// More tests covering different scenarios, such as invalid credentials, null values, etc.</span>
}
</code></pre><p>These practices will help ensure the stability and effectiveness of your codebase, allowing you to deliver high-quality software that meets the highest standards of functionality and reliability.</p>
<h3 id="heading-hands-on-exercises-for-unit-testing-in-java">Hands-On Exercises for Unit Testing in Java</h3>
<h4 id="heading-beginner-level-exercise-amp-solution">Beginner Level: Exercise &amp; Solution</h4>
<p><strong>Exercise: Testing a Sum Function</strong></p>
<p>Create a function <code>sumArray</code> that takes an array of integers and returns the sum of all the elements. Write a unit test to validate that the function correctly sums the array elements.</p>
<p>Solution with Code:</p>
<pre><code><span class="hljs-comment">// Java Method</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayOperations</span> </span>{
    public <span class="hljs-keyword">static</span> int sumArray(int[] numbers) {
        int sum = <span class="hljs-number">0</span>; <span class="hljs-comment">// Initialize sum to 0</span>
        <span class="hljs-keyword">for</span> (int num : numbers) { <span class="hljs-comment">// Iterate through each element</span>
            sum += num; <span class="hljs-comment">// Add each element to sum</span>
        }
        <span class="hljs-keyword">return</span> sum; <span class="hljs-comment">// Return the total sum</span>
    }
}

<span class="hljs-comment">// Unit Test</span>
<span class="hljs-keyword">import</span> org.junit.Assert;
<span class="hljs-keyword">import</span> org.junit.Test;

public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayOperationsTest</span> </span>{
    @Test
    public <span class="hljs-keyword">void</span> testSumArray() {
        int[] numbers = {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>}; <span class="hljs-comment">// Test array</span>
        int expectedSum = <span class="hljs-number">10</span>; <span class="hljs-comment">// Expected sum of the array elements</span>
        <span class="hljs-comment">// Assert that the sumArray method returns the correct sum</span>
        Assert.assertEquals(expectedSum, ArrayOperations.sumArray(numbers));
    }
}
</code></pre><h4 id="heading-intermediate-level-exercise-amp-solution">Intermediate Level: Exercise &amp; Solution</h4>
<p><strong>Exercise: Testing Array Equality</strong></p>
<p>Create a function <code>arraysEqual</code> that compares two arrays of integers and returns <code>true</code> if they are equal (same elements in the same order) and <code>false</code> otherwise. Write a unit test to validate the function's behavior for equal and unequal arrays.</p>
<p>Solution with Code:</p>
<pre><code><span class="hljs-comment">// Java Method</span>

<span class="hljs-comment">// Class to perform operations on arrays</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayOperations</span> </span>{
    <span class="hljs-comment">// Method to calculate the sum of elements in an array</span>
    public <span class="hljs-keyword">static</span> int sumArray(int[] numbers) {
        <span class="hljs-comment">// Initialize sum to 0</span>
        int sum = <span class="hljs-number">0</span>;
        <span class="hljs-comment">// Iterate through each element in the array</span>
        <span class="hljs-keyword">for</span> (int num : numbers) {
            <span class="hljs-comment">// Add each element to the sum</span>
            sum += num;
        }
        <span class="hljs-comment">// Return the total sum of the array elements</span>
        <span class="hljs-keyword">return</span> sum;
    }
}

<span class="hljs-comment">// Unit Test</span>

<span class="hljs-comment">// Import the necessary classes for testing</span>
<span class="hljs-keyword">import</span> org.junit.Assert;
<span class="hljs-keyword">import</span> org.junit.Test;

<span class="hljs-comment">// Define a test class for ArrayOperations</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayOperationsTest</span> </span>{
    <span class="hljs-comment">// Define a test method for the sumArray method in ArrayOperations</span>
    @Test
    public <span class="hljs-keyword">void</span> testSumArray() {
        <span class="hljs-comment">// Define a test array</span>
        int[] numbers = {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>};
        <span class="hljs-comment">// Define the expected sum of the array elements</span>
        int expectedSum = <span class="hljs-number">10</span>;
        <span class="hljs-comment">// Assert that the sumArray method returns the correct sum</span>
        Assert.assertEquals(expectedSum, ArrayOperations.sumArray(numbers));
    }
}
</code></pre><h4 id="heading-advanced-level-exercise-amp-solution">Advanced Level: Exercise &amp; Solution</h4>
<p><strong>Exercise: Testing Array Rotation</strong></p>
<p>Create a function <code>rotateArray</code> that takes an array and a positive integer <code>k</code>, and rotates the array to the right by <code>k</code> places. Write a unit test to validate the function's behavior for different values of <code>k</code>.</p>
<p>Solution with Code:</p>
<pre><code><span class="hljs-comment">// Java Method</span>

<span class="hljs-comment">// Class to perform operations on arrays</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayRotations</span> </span>{
    <span class="hljs-comment">// Method to rotate an array to the right by k positions</span>
    public <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> rotateArray(int[] array, int k) {
        <span class="hljs-comment">// Get the length of the array</span>
        int length = array.length;
        <span class="hljs-comment">// Handle rotations larger than array length</span>
        k %= length;
        <span class="hljs-comment">// Reverse the whole array</span>
        reverse(array, <span class="hljs-number">0</span>, length - <span class="hljs-number">1</span>);
        <span class="hljs-comment">// Reverse the first part</span>
        reverse(array, <span class="hljs-number">0</span>, k - <span class="hljs-number">1</span>);
        <span class="hljs-comment">// Reverse the second part</span>
        reverse(array, k, length - <span class="hljs-number">1</span>);
    }

    <span class="hljs-comment">// Method to reverse a portion of an array from index 'start' to 'end'</span>
    private <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> reverse(int[] array, int start, int end) {
        <span class="hljs-comment">// Loop until start is less than end</span>
        <span class="hljs-keyword">while</span> (start &lt; end) {
            <span class="hljs-comment">// Swap the elements at the start and end indices</span>
            int temp = array[start];
            array[start] = array[end];
            array[end] = temp;
            <span class="hljs-comment">// Increment start and decrement end</span>
            start++;
            end--;
        }
    }
}

<span class="hljs-comment">// Unit Test</span>

<span class="hljs-comment">// Import the necessary classes for testing</span>
<span class="hljs-keyword">import</span> org.junit.Assert;
<span class="hljs-keyword">import</span> org.junit.Test;

<span class="hljs-comment">// Define a test class for ArrayRotations</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayRotationsTest</span> </span>{
    <span class="hljs-comment">// Define a test method for the rotateArray method in ArrayRotations</span>
    @Test
    public <span class="hljs-keyword">void</span> testRotateArray() {
        <span class="hljs-comment">// Define a test array</span>
        int[] array = {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>};
        <span class="hljs-comment">// Define the number of rotations</span>
        int k = <span class="hljs-number">2</span>;
        <span class="hljs-comment">// Call the rotateArray method with the test array and number of rotations</span>
        ArrayRotations.rotateArray(array, k);
        <span class="hljs-comment">// Define the expected rotated array</span>
        int[] expectedRotatedArray = {<span class="hljs-number">4</span>, <span class="hljs-number">5</span>, <span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>};
        <span class="hljs-comment">// Assert that rotateArray correctly rotates the array</span>
        Assert.assertArrayEquals(expectedRotatedArray, array);
    }
}
</code></pre><p>Each example provides a clear task, solution, and comments to guide the learner through the process of writing and understanding unit tests in Java.</p>
<p> These exercises range from basic array operations to more complex tasks like array rotation, covering different aspects of array manipulation and testing.</p>
<h3 id="heading-additional-unit-testing-resources">Additional Unit Testing Resources</h3>
<ol>
<li><a target="_blank" href="https://www.freecodecamp.org/news/java-unit-testing/">Java Unit Testing Guide</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/what-is-debugging-how-to-debug-code/">What is Debugging?</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/how-to-debug-java-code-4a28442e0959/">How to Debug Java Code</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/a-beginners-guide-to-testing-implement-these-quick-checks-to-test-your-code-d50027ad5eed/">A Beginner's Guide to Testing</a></li>
</ol>
<h2 id="heading-chapter-2-file-handling-and-inputoutput-io">Chapter 2: File Handling and Input/Output (I/O)</h2>
<h3 id="heading-file-handling-in-java-using-filewriter-and-filereader">File Handling in Java using FileWriter and FileReader</h3>
<p>File handling is an essential aspect of programming, especially when it comes to reading from and writing to files. </p>
<p>In Java, file handling is accomplished using various classes and methods provided by the language's standard library. One such set of classes is <code>FileWriter</code> and <code>FileReader</code>, which are specifically designed for handling textual data.</p>
<p>This chapter explores the concepts and techniques involved in file handling using <code>FileWriter</code> and <code>FileReader</code> in Java. </p>
<p>We will discuss the importance of character streams and why choosing the right stream, such as <code>FileWriter</code> and <code>FileReader</code>, is crucial for working with textual data. We'll also delve into the constructors and methods of these classes, explore practical demonstrations, and provide exercises to enhance your understanding and proficiency in Java file handling.</p>
<h4 id="heading-what-is-filewriter">What is <code>FileWriter</code>?</h4>
<p><code>FileWriter</code> is a class in Java that is used for writing character-based data to a file. It is a subclass of the <code>OutputStream</code> class, which allows for the writing of byte-based data. </p>
<p><code>FileWriter</code> is specifically designed for handling textual data and provides convenient methods for writing characters, character arrays, and strings to a file.</p>
<h4 id="heading-constructors-of-filewriter">Constructors of <code>FileWriter</code>:</h4>
<p>There are several constructors available in <code>FileWriter</code> for creating instances of the class. These constructors provide flexibility in specifying the file to be written, the character encoding to be used, and the buffer size for efficient writing. The constructors include options for passing a File object, a FileDescriptor, or a String representing the file path.</p>
<p>It is important to choose the appropriate constructor based on the specific use case. For example, using the File constructor allows for easy manipulation of file properties, while the String-based constructor provides a more convenient way to specify the file path. Also, specifying the character encoding and buffer size can greatly impact the performance and behavior of the <code>FileWriter</code>.</p>
<h4 id="heading-methods-of-filewriter">Methods of <code>FileWriter</code>:</h4>
<p><code>FileWriter</code> provides various methods for writing data to a file. The key methods include <code>write()</code>, <code>flush()</code>, and <code>close()</code>.</p>
<p>The <code>write()</code> method allows for writing single characters, character arrays, and strings to the file. It provides flexibility in appending data to an existing file or overwriting the content of the file.</p>
<p>The <code>flush()</code> method is used to flush any buffered data to the file. This ensures that all data is written immediately and not held in memory.</p>
<p>The <code>close()</code> method is used to close the FileWriter and release any system resources associated with it. It is important to always close the FileWriter after writing to ensure that all data is properly written and resources are freed.</p>
<h4 id="heading-enhancing-performance-with-bufferedwriter">Enhancing Performance with BufferedWriter:</h4>
<p>To improve the performance of writing data to a file, you can use <code>FileWriter</code> in conjunction with <code>BufferedWriter</code>. <code>BufferedWriter</code> is a class that provides buffering capabilities, reducing the number of system calls and improving overall efficiency.</p>
<p>By wrapping the <code>FileWriter</code> with a <code>BufferedWriter</code>, data can be written to a buffer first, and then flushed to the file when necessary. This reduces the overhead of frequent disk writes and can significantly enhance the performance of file writing operations.</p>
<h3 id="heading-what-is-filereader">What is <code>FileReader</code>?</h3>
<p><code>FileReader</code> is an important class in Java that specializes in reading character streams from a file. It is a subclass of the <code>InputStreamReader</code> class, which is responsible for converting byte streams into character streams. </p>
<p><code>FileReader</code> inherits the functionality of <code>InputStreamReader</code> and provides additional methods specifically designed for reading textual data from a file.</p>
<h4 id="heading-constructors-of-filereader">Constructors of <code>FileReader</code></h4>
<p>FileReader offers several constructors that allow for different file access scenarios. These constructors provide flexibility in specifying the file to be read, the character encoding to be used, and the buffer size for efficient reading. </p>
<p>You can choose the appropriate constructor depending on your use case. For example, a <code>FileReader</code> instance can be created by passing a File object, a FileDescriptor, or a String representing the file path.</p>
<h4 id="heading-methods-of-filereader">Methods of <code>FileReader</code></h4>
<p><code>FileReader</code> provides various methods for reading data from a file. The <code>read()</code> method is the primary method used for reading characters from a file. It returns the next character in the file as an integer value, or -1 if the end of the file has been reached. </p>
<p><code>FileReader</code> also provides a <code>close()</code> method to release any system resources associated with the <code>FileReader</code> instance. It also allows for handling IOExceptions, which are exceptions that may occur during file reading operations.</p>
<h4 id="heading-java-code-to-demonstrate-filewriter">Java Code to Demonstrate <code>FileWriter</code></h4>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> java.io.FileWriter; 
<span class="hljs-keyword">import</span> java.io.IOException; 

public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FileWriterDemo</span> </span>{ 
    public <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> main(<span class="hljs-built_in">String</span>[] args) { 
        <span class="hljs-comment">// Accept a string  </span>
        <span class="hljs-built_in">String</span> str = <span class="hljs-string">"FileWriter is a class in Java used for writing character-based data to a file."</span>;

        <span class="hljs-comment">// attach a file to FileWriter  </span>
        <span class="hljs-keyword">try</span> (FileWriter fw = <span class="hljs-keyword">new</span> FileWriter(<span class="hljs-string">"output.txt"</span>)) { 
            <span class="hljs-comment">// read character wise from string and write into FileWriter  </span>
            fw.write(str); 

            <span class="hljs-comment">// message when writing successful </span>
            System.out.println(<span class="hljs-string">"Writing successful"</span>); 
        } <span class="hljs-keyword">catch</span> (IOException e) { 
            e.printStackTrace(); 
        } 
    } 
}
</code></pre>
<h3 id="heading-hands-on-exercises-and-real-world-applications">Hands-On Exercises and Real-World Applications</h3>
<h4 id="heading-how-to-write-to-a-file-using-filewriter">How to Write to a File using <code>FileWriter</code></h4>
<p><strong>Task</strong>: Create a program to write a list of students' names to a text file.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> java.io.FileWriter;
<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.util.Arrays;
<span class="hljs-keyword">import</span> java.util.List;

public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WriteStudentsList</span> </span>{
    public <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> main(<span class="hljs-built_in">String</span>[] args) {
        List&lt;<span class="hljs-built_in">String</span>&gt; students = Arrays.asList(<span class="hljs-string">"Alice"</span>, <span class="hljs-string">"Bob"</span>, <span class="hljs-string">"Charlie"</span>);

        <span class="hljs-keyword">try</span> (FileWriter writer = <span class="hljs-keyword">new</span> FileWriter(<span class="hljs-string">"students.txt"</span>)) {
            <span class="hljs-keyword">for</span> (<span class="hljs-built_in">String</span> student : students) {
                writer.write(student + <span class="hljs-string">"\\n"</span>);
            }
            System.out.println(<span class="hljs-string">"Student list written to file."</span>);
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<p><strong>Exercise</strong>: Modify the program to append new students to the existing list without overwriting the current data.</p>
<h4 id="heading-how-to-read-from-a-file-using-filereader">How to Read from a File using <code>FileReader</code></h4>
<p><strong>Task</strong>: Create a program to read the contents of the "students.txt" file created above and display them on the console.</p>
<pre><code class="lang-jsx"><span class="hljs-keyword">import</span> java.io.FileReader;
<span class="hljs-keyword">import</span> java.io.IOException;

public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ReadStudentsList</span> </span>{
    public <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> main(<span class="hljs-built_in">String</span>[] args) {
        <span class="hljs-keyword">try</span> (FileReader reader = <span class="hljs-keyword">new</span> FileReader(<span class="hljs-string">"students.txt"</span>)) {
            int character;
            <span class="hljs-keyword">while</span> ((character = reader.read()) != <span class="hljs-number">-1</span>) {
                System.out.print((char) character);
            }
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<p>Now, let's look at some practical code examples for common pitfalls in file handling using Java's <code>FileWriter</code> and <code>FileReader</code> classes, along with solutions:</p>
<h4 id="heading-file-not-found">File Not Found:</h4>
<ul>
<li><strong>Pitfall</strong>: Attempting to read from or write to a file that doesn't exist.</li>
<li><strong>Solution</strong>: Always check if the file exists before performing read/write operations. Use the <code>File</code> class to create a new file if it does not exist.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.io.File;
<span class="hljs-keyword">import</span> java.io.FileWriter;
<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CheckFileExists</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        File file = <span class="hljs-keyword">new</span> File(<span class="hljs-string">"example.txt"</span>);
        <span class="hljs-keyword">if</span> (!file.exists()) {
            <span class="hljs-keyword">try</span> {
                file.createNewFile(); <span class="hljs-comment">// Create the file if it does not exist</span>
            } <span class="hljs-keyword">catch</span> (IOException e) {
                e.printStackTrace();
            }
        }
        <span class="hljs-keyword">try</span> (FileWriter writer = <span class="hljs-keyword">new</span> FileWriter(file)) {
            writer.write(<span class="hljs-string">"Hello, world!"</span>);
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<h4 id="heading-incorrect-file-paths">Incorrect File Paths:</h4>
<ul>
<li><strong>Pitfall</strong>: Using incorrect file paths leading to <code>FileNotFoundException</code>.</li>
<li><strong>Solution</strong>: Use absolute paths for clarity or ensure the relative path is correct. Pay attention to cross-platform path separators.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">IncorrectFilePath</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        String filePath = <span class="hljs-string">"/absolute/path/to/file.txt"</span>; <span class="hljs-comment">// Use absolute path</span>
        <span class="hljs-comment">// Rest of the file handling code</span>
    }
}
</code></pre>
<h4 id="heading-resource-leakage">Resource Leakage:</h4>
<ul>
<li><strong>Pitfall</strong>: Not closing <code>FileWriter</code> or <code>FileReader</code> properly, which can lead to resource leakage.</li>
<li><strong>Solution</strong>: Use try-with-resources to ensure that file resources are automatically closed.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.io.FileReader;
<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AutoCloseFile</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> (FileReader reader = <span class="hljs-keyword">new</span> FileReader(<span class="hljs-string">"example.txt"</span>)) {
            <span class="hljs-keyword">int</span> character;
            <span class="hljs-keyword">while</span> ((character = reader.read()) != -<span class="hljs-number">1</span>) {
                System.out.print((<span class="hljs-keyword">char</span>) character);
            }
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<h4 id="heading-overwriting-file-content">Overwriting File Content:</h4>
<ul>
<li><strong>Pitfall</strong>: Accidentally overwriting existing file content.</li>
<li><strong>Solution</strong>: Use the <code>FileWriter</code> constructor that allows for appending content (<code>new FileWriter("filename.txt", true)</code>).</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.io.FileWriter;
<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AppendToFile</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> (FileWriter writer = <span class="hljs-keyword">new</span> FileWriter(<span class="hljs-string">"example.txt"</span>, <span class="hljs-keyword">true</span>)) { <span class="hljs-comment">// Append mode</span>
            writer.write(<span class="hljs-string">"\\nMore content"</span>);
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<h4 id="heading-character-encoding-issues">Character Encoding Issues:</h4>
<ul>
<li><strong>Pitfall</strong>: Issues with character encoding leading to corrupted file data.</li>
<li><strong>Solution</strong>: Be aware of the platform's default charset. Specify charset explicitly if handling non-text files or special character sets.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.io.OutputStreamWriter;
<span class="hljs-keyword">import</span> java.io.FileOutputStream;
<span class="hljs-keyword">import</span> java.io.IOException;
<span class="hljs-keyword">import</span> java.nio.charset.StandardCharsets;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CharsetExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> (OutputStreamWriter writer = <span class="hljs-keyword">new</span> OutputStreamWriter(<span class="hljs-keyword">new</span> FileOutputStream(<span class="hljs-string">"example.txt"</span>), StandardCharsets.UTF_8)) {
            writer.write(<span class="hljs-string">"Text with UTF-8 encoding"</span>);
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<h4 id="heading-buffering-for-performance">Buffering for Performance:</h4>
<ul>
<li><strong>Pitfall</strong>: Inefficient file writing/reading operations.</li>
<li><strong>Solution</strong>: Use <code>BufferedWriter</code> or <code>BufferedReader</code> for efficient reading and writing operations.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.io.BufferedWriter;
<span class="hljs-keyword">import</span> java.io.FileWriter;
<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BufferedWriterExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> (BufferedWriter writer = <span class="hljs-keyword">new</span> BufferedWriter(<span class="hljs-keyword">new</span> FileWriter(<span class="hljs-string">"example.txt"</span>))) {
            writer.write(<span class="hljs-string">"Efficient writing using BufferedWriter"</span>);
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<p>These examples demonstrate practical solutions to overcome common challenges encountered in file handling in Java.</p>
<p>File handling is a fundamental aspect of programming, and in Java, it can be effectively accomplished using the <code>FileWriter</code> and <code>FileReader</code> classes.</p>
<p><code>FileWriter</code> is specifically designed for writing character-based data to a file, offering convenient methods for writing characters, character arrays, and strings. On the other hand, <code>FileReader</code> specializes in reading character streams from a file, providing additional methods for reading textual data.</p>
<h3 id="heading-byte-streams-vs-character-streams">Byte Streams vs Character Streams</h3>
<p>In this section, you'll learn about the concept of streams in Java. Streams are an essential part of the Java I/O (Input/Output) model, allowing the transfer of data between a program and an external source or destination. </p>
<p>There are two main types of streams in Java: Byte Streams and Character Streams.</p>
<p>Byte Streams are used for 8-bit byte operations and are commonly employed for reading and writing binary data. They are particularly useful when dealing with files or streams that contain non-textual information, such as images or audio files.</p>
<p>Examples of key Java classes associated with Byte Streams include <code>FileInputStream</code> and <code>FileOutputStream</code>.</p>
<p>On the other hand, Character Streams are designed for 16-bit Unicode operations and are primarily used for reading and writing textual data. They are especially suitable when working with text files or when you need to handle character-based input or output. </p>
<p>Important Java classes for Character Streams include <code>FileReader</code> and <code>FileWriter</code>.</p>
<h4 id="heading-advantages-and-limitations-of-byte-and-character-streams">Advantages and Limitations of Byte and Character Streams</h4>
<p>To effectively utilize Byte Streams and Character Streams in your Java programs, here are some practical recommendations:</p>
<ol>
<li>Choose the appropriate stream type based on the nature of your data. If you are working with binary data or non-textual information, Byte Streams provide efficient operations for handling such data. But if your application primarily deals with textual data, such as log files or user-generated content, Character Streams are the recommended choice.</li>
<li>Use the appropriate Java classes associated with each stream type. For Byte Streams, use classes like <code>FileInputStream</code> and <code>FileOutputStream</code> for reading from and writing to files. For Character Streams, use classes like <code>FileReader</code> and <code>FileWriter</code> for reading and writing text data.</li>
<li>Handle exceptions properly and close streams to avoid resource leaks. This ensures smooth data transfer and manipulation, enhancing the overall performance and reliability of your Java applications.</li>
</ol>
<h4 id="heading-byte-stream-and-character-stream-code-examples">Byte Stream and Character Stream Code Examples</h4>
<p>Here's an advanced code example that demonstrates the use of Byte Streams and Character Streams in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.io.*;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">StreamExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        String inputFilePath = <span class="hljs-string">"input.txt"</span>;
        String outputFilePath = <span class="hljs-string">"output.txt"</span>;

        <span class="hljs-comment">// Example using Byte Streams</span>
        <span class="hljs-keyword">try</span> (FileInputStream fis = <span class="hljs-keyword">new</span> FileInputStream(inputFilePath);
             FileOutputStream fos = <span class="hljs-keyword">new</span> FileOutputStream(outputFilePath)) {

            <span class="hljs-keyword">byte</span>[] buffer = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[<span class="hljs-number">1024</span>];
            <span class="hljs-keyword">int</span> bytesRead;
            <span class="hljs-keyword">while</span> ((bytesRead = fis.read(buffer)) != -<span class="hljs-number">1</span>) {
                <span class="hljs-comment">// Process the binary data</span>
                <span class="hljs-comment">// Example: Encrypt the data</span>
                <span class="hljs-keyword">byte</span>[] encryptedData = encryptData(buffer, bytesRead);

                <span class="hljs-comment">// Write the encrypted data to the output file</span>
                fos.write(encryptedData);
            }

        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }

        <span class="hljs-comment">// Example using Character Streams</span>
        <span class="hljs-keyword">try</span> (FileReader fr = <span class="hljs-keyword">new</span> FileReader(inputFilePath);
             FileWriter fw = <span class="hljs-keyword">new</span> FileWriter(outputFilePath)) {

            BufferedReader br = <span class="hljs-keyword">new</span> BufferedReader(fr);
            BufferedWriter bw = <span class="hljs-keyword">new</span> BufferedWriter(fw);

            String line;
            <span class="hljs-keyword">while</span> ((line = br.readLine()) != <span class="hljs-keyword">null</span>) {
                <span class="hljs-comment">// Process the text data</span>
                <span class="hljs-comment">// Example: Convert the text to uppercase</span>
                String processedLine = line.toUpperCase();

                <span class="hljs-comment">// Write the processed line to the output file</span>
                bw.write(processedLine);
                bw.newLine();
            }

        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">byte</span>[] encryptData(<span class="hljs-keyword">byte</span>[] data, <span class="hljs-keyword">int</span> length) {
        <span class="hljs-comment">// Example encryption logic</span>
        <span class="hljs-comment">// This is just a placeholder and does not represent a secure encryption algorithm</span>
        <span class="hljs-keyword">byte</span>[] encryptedData = <span class="hljs-keyword">new</span> <span class="hljs-keyword">byte</span>[length];
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; length; i++) {
            encryptedData[i] = (<span class="hljs-keyword">byte</span>) (data[i] + <span class="hljs-number">1</span>);
        }
        <span class="hljs-keyword">return</span> encryptedData;
    }
}
</code></pre>
<p>In this code example, we have two sections: one demonstrating the use of Byte Streams and another demonstrating the use of Character Streams.</p>
<p>For Byte Streams, we use <code>FileInputStream</code> to read binary data from an input file (<code>input.txt</code>). We read the data in chunks using a byte buffer and process the data (in this case, encrypting it). Then, we use <code>FileOutputStream</code> to write the encrypted data to an output file (<code>output.txt</code>).</p>
<p>For Character Streams, we use <code>FileReader</code> to read text data from the same input file. We read the data line by line using a <code>BufferedReader</code>, process the data (in this case, converting it to uppercase), and use <code>FileWriter</code> and <code>BufferedWriter</code> to write the processed data to the output file.</p>
<p>These examples showcase the practical use of Byte Streams and Character Streams for handling binary and textual data, respectively.</p>
<p>Remember to handle exceptions properly and close the streams after use to ensure efficient and reliable stream-based operations in your Java programs.</p>
<p>When choosing between Byte Streams and Character Streams in Java, consider the nature of your data and the specific requirements of your application. </p>
<p>For non-textual or binary data, use Byte Streams. For textual data, use Character Streams. Handle exceptions properly and close streams after use. </p>
<p>By understanding the advantages and limitations of each stream type, you can make informed decisions and ensure efficient data processing in your Java applications.</p>
<h3 id="heading-how-to-handle-exceptions-in-io">How to Handle Exceptions in I/O</h3>
<h4 id="heading-java-exception-basics">Java Exception Basics</h4>
<p>In the realm of Java programming, understanding exceptions is crucial for writing reliable and maintainable code. Exceptions in Java refer to conditions that disrupt the normal flow of a program. They are classified based on their nature to handle errors or exceptional situations that arise during runtime.</p>
<p>Java handles exceptions using "try-catch" blocks, allowing programmers to isolate and manage error conditions effectively. This understanding is key to anticipating and addressing potential issues, leading to more robust code.</p>
<p>Familiarity with the wide range of Java exceptions is important for precise error reporting and targeted handling. Best practices in throwing exceptions include adhering to Java’s syntax and guidelines, and judicious use of custom exceptions to improve code clarity and maintainability.</p>
<p>Exception handling extends beyond "try-catch" blocks. The "finally" block is used for cleanup operations, ensuring resource release regardless of exception occurrence. Nested try-catch structures provide fine-grained control over error management.</p>
<h4 id="heading-anatomy-of-a-java-exception">Anatomy of a Java Exception</h4>
<p>In Java, we can use the <code>try-catch</code> blocks to isolate and handle exceptions. Here's an example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Code that might throw an exception</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (Exception e) {
    <span class="hljs-comment">// Exception handling code</span>
    <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>By catching the exception, we can gracefully recover from error conditions and prevent our program from crashing.</p>
<p>Java provides a wide range of exception types to choose from. Let's say we have a method that reads data from a file. We can handle specific exceptions that might occur, such as <code>FileNotFoundException</code> and <code>IOException</code>. Here's an example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Code that reads data from a file</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (FileNotFoundException e) {
    <span class="hljs-comment">// Handle file not found exception</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (IOException e) {
    <span class="hljs-comment">// Handle IO exception</span>
    <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>By handling specific exceptions, we can provide more precise error reporting and targeted exception handling.</p>
<p>In addition to <code>try-catch</code> blocks, we can use the <code>finally</code> block for cleanup operations. For example, if we open a file in the <code>try</code> block, we can ensure that the file is properly closed in the <code>finally</code> block, regardless of whether an exception occurs. Here's an example:</p>
<pre><code class="lang-java">FileWriter fileWriter = <span class="hljs-keyword">null</span>;
<span class="hljs-keyword">try</span> {
    fileWriter = <span class="hljs-keyword">new</span> FileWriter(<span class="hljs-string">"output.txt"</span>);
    <span class="hljs-comment">// Code that writes data to the file</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (IOException e) {
    <span class="hljs-comment">// Handle IO exception</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">finally</span> {
    <span class="hljs-keyword">if</span> (fileWriter != <span class="hljs-keyword">null</span>) {
        <span class="hljs-keyword">try</span> {
            fileWriter.close();
        } <span class="hljs-keyword">catch</span> (IOException e) {
            <span class="hljs-comment">// Handle exception while closing the file</span>
            <span class="hljs-comment">// ...</span>
        }
    }
}
</code></pre>
<p>Nested <code>try-catch</code> structures provide fine-grained control over error management. We can handle exceptions at different levels, depending on the specific needs of our program. Here's an example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Outer try block</span>
    <span class="hljs-comment">// ...</span>
    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// Inner try block</span>
        <span class="hljs-comment">// ...</span>
    } <span class="hljs-keyword">catch</span> (Exception e) {
        <span class="hljs-comment">// Handle exception from inner try block</span>
        <span class="hljs-comment">// ...</span>
    }
} <span class="hljs-keyword">catch</span> (Exception e) {
    <span class="hljs-comment">// Handle exception from outer try block</span>
    <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>By understanding these concepts and applying best practices, we can write robust and error-resistant Java code.</p>
<p>Remember to keep code simplicity in mind. By applying practical advice and taking action, reliable and maintainable Java applications can be built.</p>
<h4 id="heading-throwing-exceptions">Throwing Exceptions</h4>
<p>When it comes to handling exceptions in Java, it is essential to understand the syntax for throwing exceptions, creating custom exceptions, and following best practices.</p>
<p>To throw an exception in Java, you can use the <code>throw</code> keyword followed by the exception object. This allows you to explicitly indicate that a specific error condition has occurred. For example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IOException(<span class="hljs-string">"File not found"</span>);
</code></pre>
<p>By throwing exceptions, you can provide more detailed and meaningful error messages to assist in troubleshooting and debugging.</p>
<p>Creating custom exceptions in Java enables you to handle specific error scenarios in a more precise and targeted manner. By extending the <code>Exception</code> class or one of its subclasses, you can define your own exception types. For example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CustomException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exception</span> </span>{
    <span class="hljs-comment">// Constructor and additional methods</span>
}
</code></pre>
<p>Custom exceptions can be useful for encapsulating complex logic or specific error conditions within your code. They improve code readability and make it easier to identify and handle exceptional situations.</p>
<p>To ensure effective exception handling, it is important to follow best practices. Here are a few recommendations:</p>
<ol>
<li><strong>Be specific in exception handling</strong>: Catch exceptions at the right level of abstraction to handle them appropriately. Consider the specific exception types that can be thrown and handle them accordingly.</li>
<li><strong>Provide meaningful error messages</strong>: Exception messages should clearly indicate the cause and context of the error. This helps developers understand and resolve issues more efficiently.</li>
<li><strong>Keep exception handling minimal</strong>: Only catch exceptions that you can handle effectively. Rethrowing or propagating exceptions may be necessary in some cases to allow higher-level code to handle them appropriately.</li>
<li><strong>Clean up resources</strong>: Use the <code>finally</code> block to release resources that were acquired within a <code>try</code> block, ensuring proper cleanup regardless of whether an exception occurs.</li>
<li><strong>Log exceptions</strong>: Logging exceptions helps in diagnosing and troubleshooting issues. Include relevant information such as stack traces, input values, and any other contextual details that may assist in resolving the problem.</li>
</ol>
<p>Here's an advanced code example that demonstrates exception handling in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FileProcessor</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processFile</span><span class="hljs-params">(String fileName)</span> <span class="hljs-keyword">throws</span> IOException </span>{
        <span class="hljs-keyword">try</span> (BufferedReader reader = <span class="hljs-keyword">new</span> BufferedReader(<span class="hljs-keyword">new</span> FileReader(fileName))) {
            String line;
            <span class="hljs-keyword">while</span> ((line = reader.readLine()) != <span class="hljs-keyword">null</span>) {
                <span class="hljs-comment">// Process each line of the file</span>
                <span class="hljs-comment">// ...</span>
            }
        } <span class="hljs-keyword">catch</span> (FileNotFoundException e) {
            System.err.println(<span class="hljs-string">"File not found: "</span> + fileName);
            <span class="hljs-keyword">throw</span> e; <span class="hljs-comment">// Rethrow the exception to allow higher-level code to handle it</span>
        } <span class="hljs-keyword">catch</span> (IOException e) {
            System.err.println(<span class="hljs-string">"Error reading file: "</span> + e.getMessage());
            <span class="hljs-keyword">throw</span> e; <span class="hljs-comment">// Rethrow the exception to allow higher-level code to handle it</span>
        }
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        FileProcessor fileProcessor = <span class="hljs-keyword">new</span> FileProcessor();
        <span class="hljs-keyword">try</span> {
            fileProcessor.processFile(<span class="hljs-string">"input.txt"</span>);
        } <span class="hljs-keyword">catch</span> (IOException e) {
            System.err.println(<span class="hljs-string">"An error occurred while processing the file: "</span> + e.getMessage());
        }
    }
}
</code></pre>
<p>In this example, the <code>FileProcessor</code> class has a method <code>processFile()</code> that reads lines from a file. It uses a <code>try-with-resources</code> block to automatically close the <code>BufferedReader</code> after processing the file. If the file is not found or an error occurs while reading the file, the corresponding exceptions (<code>FileNotFoundException</code> and <code>IOException</code>) are caught and handled. The exceptions are also rethrown to allow the higher-level code (in this case, the <code>main()</code> method) to handle them if needed.</p>
<h4 id="heading-unchecked-exceptions">Unchecked Exceptions</h4>
<p>Unchecked exceptions are exceptions that do not require explicit handling by the programmer. They are subclasses of the <code>RuntimeException</code> class or its subclasses. </p>
<p>Unchecked exceptions are often caused by programming errors or unexpected conditions that may occur during runtime. Examples of unchecked exceptions include <code>NullPointerException</code>, <code>ArrayIndexOutOfBoundsException</code>, and <code>IllegalArgumentException</code>.</p>
<p>When dealing with unchecked exceptions, it is important to follow best practices to prevent these exceptions from occurring. This includes validating inputs and ensuring proper error handling and defensive programming. </p>
<h4 id="heading-checked-exceptions">Checked Exceptions</h4>
<p>Checked exceptions are exceptions that must be explicitly handled or declared in the method signature using the <code>throws</code> keyword. They are subclasses of the <code>Exception</code> class (excluding subclasses of <code>RuntimeException</code>). </p>
<p>Checked exceptions are typically used for conditions that are beyond the control of the program, such as I/O errors or network failures. Examples of checked exceptions include <code>IOException</code>, <code>SQLException</code>, and <code>FileNotFoundException</code>.</p>
<p>When handling checked exceptions, it is important to consider the appropriate handling strategy based on the specific situation. This may involve wrapping the checked exception in a custom unchecked exception, logging the exception, or propagating the exception to higher-level code for handling. </p>
<h4 id="heading-example-code-unchecked-and-checked-exceptions">Example Code – Unchecked and Checked Exceptions</h4>
<p>Here are additional examples that demonstrate the handling of unchecked and checked exceptions:</p>
<p><strong>Unchecked Exception Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DivisionCalculator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">divide</span><span class="hljs-params">(<span class="hljs-keyword">int</span> dividend, <span class="hljs-keyword">int</span> divisor)</span> </span>{
        <span class="hljs-keyword">if</span> (divisor == <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ArithmeticException(<span class="hljs-string">"Divisor cannot be zero"</span>);
        }
        <span class="hljs-keyword">return</span> dividend / divisor;
    }
}
</code></pre>
<p>In this example, the <code>divide</code> method calculates the result of dividing the <code>dividend</code> by the <code>divisor</code>. If the <code>divisor</code> is zero, an unchecked exception of type <code>ArithmeticException</code> is thrown. This ensures that the code explicitly handles the case where division by zero occurs.</p>
<p><strong>Checked Exception Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FileReader</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">readFile</span><span class="hljs-params">(String fileName)</span> <span class="hljs-keyword">throws</span> IOException </span>{
        BufferedReader reader = <span class="hljs-keyword">null</span>;
        <span class="hljs-keyword">try</span> {
            reader = <span class="hljs-keyword">new</span> BufferedReader(<span class="hljs-keyword">new</span> java.io.FileReader(fileName));
            StringBuilder content = <span class="hljs-keyword">new</span> StringBuilder();
            String line;
            <span class="hljs-keyword">while</span> ((line = reader.readLine()) != <span class="hljs-keyword">null</span>) {
                content.append(line).append(<span class="hljs-string">"\\\\n"</span>);
            }
            <span class="hljs-keyword">return</span> content.toString();
        } <span class="hljs-keyword">finally</span> {
            <span class="hljs-keyword">if</span> (reader != <span class="hljs-keyword">null</span>) {
                reader.close();
            }
        }
    }
}
</code></pre>
<p>In this example, the <code>readFile</code> method reads the contents of a file specified by the <code>fileName</code> parameter. The method declares that it may throw an <code>IOException</code> (a checked exception) using the <code>throws</code> keyword. This allows the caller of the method to handle the exception or propagate it further up the call stack.</p>
<p>Understanding the differences between unchecked and checked exceptions is essential for effective exception handling in Java. By following best practices, handling exceptions appropriately, and considering the specific needs of your application, you can write robust and reliable Java code. </p>
<p>Remember to continuously improve your exception handling skills and stay up to date with industry best practices to ensure the highest quality in your code.</p>
<h3 id="heading-real-world-examples-of-exception-handling">Real-World Examples of Exception Handling:</h3>
<p>Here are some additional code examples for each of the topics we've just discussed:</p>
<h4 id="heading-practical-applications-in-java-applications">Practical Applications in Java Applications:</h4>
<pre><code class="lang-java"><span class="hljs-comment">// Example 1: Exception handling in file processing</span>
<span class="hljs-keyword">try</span> {
    FileReader fileReader = <span class="hljs-keyword">new</span> FileReader(<span class="hljs-string">"input.txt"</span>);
    <span class="hljs-comment">// Code to process the file</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (FileNotFoundException e) {
    System.err.println(<span class="hljs-string">"File not found: "</span> + e.getMessage());
} <span class="hljs-keyword">catch</span> (IOException e) {
    System.err.println(<span class="hljs-string">"Error reading file: "</span> + e.getMessage());
}

<span class="hljs-comment">// Example 2: Exception handling in network communication</span>
<span class="hljs-keyword">try</span> {
    Socket socket = <span class="hljs-keyword">new</span> Socket(<span class="hljs-string">"localhost"</span>, <span class="hljs-number">8080</span>);
    <span class="hljs-comment">// Code to communicate over the network</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (UnknownHostException e) {
    System.err.println(<span class="hljs-string">"Unknown host: "</span> + e.getMessage());
} <span class="hljs-keyword">catch</span> (IOException e) {
    System.err.println(<span class="hljs-string">"Error communicating over the network: "</span> + e.getMessage());
}

<span class="hljs-comment">// Example 3: Exception handling in database operations</span>
<span class="hljs-keyword">try</span> {
    Connection connection = DriverManager.getConnection(<span class="hljs-string">"jdbc:mysql://localhost:3306/mydatabase"</span>, <span class="hljs-string">"username"</span>, <span class="hljs-string">"password"</span>);
    <span class="hljs-comment">// Code to perform database operations</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (SQLException e) {
    System.err.println(<span class="hljs-string">"Database error: "</span> + e.getMessage());
}
</code></pre>
<h4 id="heading-common-scenarios-for-exception-handling">Common Scenarios for Exception Handling:</h4>
<pre><code class="lang-java"><span class="hljs-comment">// Example 1: Handling division by zero</span>
<span class="hljs-keyword">int</span> dividend = <span class="hljs-number">10</span>;
<span class="hljs-keyword">int</span> divisor = <span class="hljs-number">0</span>;

<span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">double</span> result = dividend / divisor;
    System.out.println(<span class="hljs-string">"Result: "</span> + result);
} <span class="hljs-keyword">catch</span> (ArithmeticException e) {
    System.err.println(<span class="hljs-string">"Error: "</span> + e.getMessage());
}

<span class="hljs-comment">// Example 2: Handling array index out of bounds</span>
<span class="hljs-keyword">int</span>[] numbers = {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>};

<span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">int</span> value = numbers[<span class="hljs-number">3</span>];
    System.out.println(<span class="hljs-string">"Value: "</span> + value);
} <span class="hljs-keyword">catch</span> (ArrayIndexOutOfBoundsException e) {
    System.err.println(<span class="hljs-string">"Error: "</span> + e.getMessage());
}

<span class="hljs-comment">// Example 3: Handling null pointer exception</span>
String name = <span class="hljs-keyword">null</span>;

<span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">int</span> length = name.length();
    System.out.println(<span class="hljs-string">"Length: "</span> + length);
} <span class="hljs-keyword">catch</span> (NullPointerException e) {
    System.err.println(<span class="hljs-string">"Error: "</span> + e.getMessage());
}
</code></pre>
<h4 id="heading-learning-from-real-world-cases">Learning from Real-World Cases:</h4>
<pre><code class="lang-java"><span class="hljs-comment">// Example 1: Handling file processing errors</span>
<span class="hljs-keyword">try</span> {
    FileReader fileReader = <span class="hljs-keyword">new</span> FileReader(<span class="hljs-string">"input.txt"</span>);
    <span class="hljs-comment">// Code to process the file</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (IOException e) {
    System.err.println(<span class="hljs-string">"Error processing file: "</span> + e.getMessage());
}

<span class="hljs-comment">// Example 2: Handling database connection errors</span>
<span class="hljs-keyword">try</span> {
    Connection connection = DriverManager.getConnection(<span class="hljs-string">"jdbc:mysql://localhost:3306/mydatabase"</span>, <span class="hljs-string">"username"</span>, <span class="hljs-string">"password"</span>);
    <span class="hljs-comment">// Code to perform database operations</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (SQLException e) {
    System.err.println(<span class="hljs-string">"Error connecting to database: "</span> + e.getMessage());
}

<span class="hljs-comment">// Example 3: Handling network communication errors</span>
<span class="hljs-keyword">try</span> {
    Socket socket = <span class="hljs-keyword">new</span> Socket(<span class="hljs-string">"localhost"</span>, <span class="hljs-number">8080</span>);
    <span class="hljs-comment">// Code to communicate over the network</span>
    <span class="hljs-comment">// ...</span>
} <span class="hljs-keyword">catch</span> (IOException e) {
    System.err.println(<span class="hljs-string">"Error communicating over the network: "</span> + e.getMessage());
}
</code></pre>
<p>These examples demonstrate various scenarios where exception handling is commonly applied in Java applications. The comments in the code provide explanations and instructions for each scenario.</p>
<p>Remember to adapt the code to your specific needs and handle exceptions according to your application's requirements.</p>
<h3 id="heading-advanced-exception-handling-techniques">Advanced Exception Handling Techniques</h3>
<p>When it comes to advanced exception handling techniques in Java, there are several key aspects to consider.</p>
<p><strong>Utilizing the <code>throws</code> Keyword:</strong> The <code>throws</code> keyword is used to indicate that a method may throw a particular exception. By declaring checked exceptions in the method signature, we can ensure that the calling code handles or propagates the exception. </p>
<p>This has a significant impact on code design and maintenance. Proper use of the <code>throws</code> keyword promotes clarity and forces developers to consider exception handling requirements upfront. It also allows for more modular and flexible code, as exceptions can be handled at different levels in the call stack.</p>
<pre><code class="lang-jsx">public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FileProcessor</span> </span>{

    <span class="hljs-comment">// This method declares that it may throw an IOException</span>
    public <span class="hljs-keyword">void</span> readFile(<span class="hljs-built_in">String</span> fileName) throws IOException {
        FileInputStream file = <span class="hljs-keyword">new</span> FileInputStream(fileName);
        <span class="hljs-comment">// Read and process the file</span>
        file.close();
    }
}
</code></pre>
<p><strong>Exception Chaining and Cause Analysis:</strong> Exception chaining involves linking exceptions together to provide a comprehensive view of the error chain. By utilizing exception chaining, we can identify the root cause of an exception and facilitate effective troubleshooting. </p>
<p>Techniques such as logging stack traces and analyzing exception causes enable us to gain insights into the underlying issues. </p>
<p>Real-world use cases for exception chaining include debugging complex scenarios and providing detailed error reports to aid in issue resolution.</p>
<pre><code class="lang-jsx">public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DatabaseConnector</span> </span>{

    public <span class="hljs-keyword">void</span> connectToDatabase() {
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Database connection logic</span>
        } <span class="hljs-keyword">catch</span> (SQLException e) {
            <span class="hljs-comment">// Chaining the exception with a custom message</span>
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> DatabaseConnectionException(<span class="hljs-string">"Failed to connect to database"</span>, e);
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DatabaseConnectionException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exception</span> </span>{
    public DatabaseConnectionException(<span class="hljs-built_in">String</span> message, Throwable cause) {
        <span class="hljs-built_in">super</span>(message, cause);
    }
}
</code></pre>
<p><strong>Familiarize yourself with various best practices</strong>: Writing robust and error-resistant code involves following best practices for exception handling. It is important to handle exceptions at the appropriate level of abstraction, providing meaningful error messages and logging relevant information. </p>
<p>Avoiding common mistakes, such as catching exceptions unnecessarily or swallowing exceptions, ensures that exceptions are properly addressed. </p>
<pre><code class="lang-jsx">public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DataProcessor</span> </span>{

    public <span class="hljs-keyword">void</span> processData(File dataFile) {
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Code to process data</span>
        } <span class="hljs-keyword">catch</span> (DataFormatException e) {
            <span class="hljs-comment">// Log and throw a custom exception with meaningful message</span>
            System.err.println(<span class="hljs-string">"Data format error: "</span> + e.getMessage());
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ProcessingException(<span class="hljs-string">"Invalid data format in file: "</span> + dataFile.getName(), e);
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ProcessingException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exception</span> </span>{
    public ProcessingException(<span class="hljs-built_in">String</span> message, Throwable cause) {
        <span class="hljs-built_in">super</span>(message, cause);
    }
}
</code></pre>
<p><strong>Logging and Diagnosing Exceptions:</strong> Logging exceptions plays a vital role in diagnosing and troubleshooting issues. By integrating logging with exception handling, we can capture valuable information such as stack traces, input values, and contextual details. This facilitates efficient debugging and helps in resolving problems effectively. </p>
<p>Utilizing tools and strategies for effective logging and diagnosis enhances the error analysis process and aids in producing actionable insights.</p>
<pre><code class="lang-jsx">public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">NetworkUtils</span> </span>{

    private <span class="hljs-keyword">static</span> final Logger logger = Logger.getLogger(NetworkUtils.class.getName());

    public <span class="hljs-keyword">void</span> sendDataOverNetwork(<span class="hljs-built_in">String</span> data, <span class="hljs-built_in">String</span> endpoint) {
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Code to send data</span>
        } <span class="hljs-keyword">catch</span> (NetworkException e) {
            <span class="hljs-comment">// Log the stack trace and details</span>
            logger.log(Level.SEVERE, <span class="hljs-string">"Failed to send data to "</span> + endpoint, e);
        }
    }
}
</code></pre>
<p><strong>Advanced Scenarios:</strong> By employing techniques such as multi-catch blocks or handling exceptions at different levels, we can effectively manage multiple exceptions. </p>
<p>Resource management in exceptions is another crucial aspect, ensuring that resources are properly released even in the presence of exceptions. </p>
<p>Exception handling in concurrent programming requires careful synchronization and error handling strategies to maintain data integrity and prevent race conditions.</p>
<pre><code class="lang-jsx">public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ResourceHandler</span> </span>{

    public <span class="hljs-keyword">void</span> handleResources() {
        Resource resource1 = <span class="hljs-literal">null</span>;
        Resource resource2 = <span class="hljs-literal">null</span>;
        <span class="hljs-keyword">try</span> {
            resource1 = <span class="hljs-keyword">new</span> Resource(<span class="hljs-string">"Resource1"</span>);
            resource2 = <span class="hljs-keyword">new</span> Resource(<span class="hljs-string">"Resource2"</span>);
            <span class="hljs-comment">// Work with resources</span>
        } <span class="hljs-keyword">catch</span> (ResourceException | AnotherResourceException e) {
            <span class="hljs-comment">// Handle multiple types of exceptions</span>
            System.err.println(<span class="hljs-string">"Resource handling error: "</span> + e.getMessage());
        } <span class="hljs-keyword">finally</span> {
            <span class="hljs-comment">// Ensure resources are closed</span>
            closeResource(resource1);
            closeResource(resource2);
        }
    }

    private <span class="hljs-keyword">void</span> closeResource(Resource resource) {
        <span class="hljs-keyword">if</span> (resource != <span class="hljs-literal">null</span>) {
            <span class="hljs-keyword">try</span> {
                resource.close();
            } <span class="hljs-keyword">catch</span> (ResourceException e) {
                System.err.println(<span class="hljs-string">"Failed to close resource: "</span> + e.getMessage());
            }
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Resource</span> <span class="hljs-title">implements</span> <span class="hljs-title">AutoCloseable</span> </span>{
    private <span class="hljs-built_in">String</span> name;

    public Resource(<span class="hljs-built_in">String</span> name) throws ResourceException {
        <span class="hljs-built_in">this</span>.name = name;
        <span class="hljs-comment">// Initialization logic</span>
    }

    public <span class="hljs-keyword">void</span> close() throws ResourceException {
        <span class="hljs-comment">// Clean-up logic</span>
    }
}
</code></pre>
<h3 id="heading-advanced-and-custom-exception-handling-case-studies">Advanced and Custom Exception Handling Case Studies:</h3>
<p>Analyzing real-world examples of exception handling can provide valuable insights. By studying industry cases, we can learn from successful approaches and identify common patterns. Analyzing exception handling patterns allows us to apply proven techniques and adapt them to our specific needs. </p>
<p>By solving complex problems with exception handling, we can develop expertise in handling challenging scenarios and build robust applications.</p>
<p>Remember, when writing code, it is important to keep it simple and concise. Use clear and straightforward examples to illustrate concepts. By applying practical advice and continuously improving your exception handling skills, you can develop reliable and maintainable Java applications.</p>
<p>Here's an example code snippet that demonstrates the use of custom exceptions and exception handling techniques:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FileValidator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">validateFile</span><span class="hljs-params">(String fileName)</span> <span class="hljs-keyword">throws</span> FileValidationException </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Code to validate the file</span>
            <span class="hljs-keyword">if</span> (!isFileValid(fileName)) {
                <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> FileValidationException(<span class="hljs-string">"Invalid file: "</span> + fileName);
            }
        } <span class="hljs-keyword">catch</span> (IOException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> FileValidationException(<span class="hljs-string">"Error validating file: "</span> + fileName, e);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isFileValid</span><span class="hljs-params">(String fileName)</span> <span class="hljs-keyword">throws</span> IOException </span>{
        <span class="hljs-comment">// Code to validate the file contents</span>
        <span class="hljs-comment">// ...</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        FileValidator fileValidator = <span class="hljs-keyword">new</span> FileValidator();
        <span class="hljs-keyword">try</span> {
            fileValidator.validateFile(<span class="hljs-string">"data.txt"</span>);
            System.out.println(<span class="hljs-string">"File validation successful"</span>);
        } <span class="hljs-keyword">catch</span> (FileValidationException e) {
            System.err.println(<span class="hljs-string">"File validation failed: "</span> + e.getMessage());
        }
    }
}
</code></pre>
<p>In this example, the <code>FileValidator</code> class demonstrates the use of a custom exception, <code>FileValidationException</code>, which is thrown when a file fails validation. The <code>validateFile</code> method catches any <code>IOException</code> that occurs during file validation and rethrows it as a <code>FileValidationException</code> to provide a clear and meaningful error message. The <code>Main</code> class demonstrates the handling of the custom exception, allowing for specific error reporting and appropriate exception handling.</p>
<p>By applying these techniques and principles, you can effectively handle exceptions in Java and develop high-quality code. Remember to always strive for simplicity, clarity, and continuous improvement in your exception handling practices.</p>
<h2 id="heading-chapter-3-deadlocks-and-how-to-avoid-them">Chapter 3: Deadlocks and How to Avoid Them</h2>
<p>Deadlock is a situation in Java multithreading where two or more threads are blocked forever, waiting for each other to release resources. Understanding deadlock is crucial for writing robust concurrent code.</p>
<p>There are four necessary and sufficient conditions for a deadlock to occur: mutual exclusion, hold and wait, no preemption, and circular wait.</p>
<ul>
<li>Mutual exclusion means that a resource can only be used by one thread at a time. </li>
<li>Hold and wait refers to a situation where a thread holds a resource and is waiting to acquire another resource. </li>
<li>No preemption implies that resources cannot be forcefully taken away from a thread. </li>
<li>Circular wait occurs when a cycle of threads exists, where each thread is waiting for a resource that is held by another thread in the cycle.</li>
</ul>
<p>To better illustrate this concept, consider the following code snippet:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockExample</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object resource1 = <span class="hljs-keyword">new</span> Object();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object resource2 = <span class="hljs-keyword">new</span> Object();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource1) {
            <span class="hljs-comment">// Do something with resource1</span>
            <span class="hljs-keyword">synchronized</span> (resource2) {
                <span class="hljs-comment">// Do something with resource2</span>
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource2) {
            <span class="hljs-comment">// Do something with resource2</span>
            <span class="hljs-keyword">synchronized</span> (resource1) {
                <span class="hljs-comment">// Do something with resource1</span>
            }
        }
    }
}
</code></pre>
<p>In this example, two threads call <code>method1</code> and <code>method2</code> concurrently. If one thread acquires <code>resource1</code> and waits for <code>resource2</code>, while the other thread acquires <code>resource2</code> and waits for <code>resource1</code>, a deadlock occurs.</p>
<p>To avoid deadlocks, it is essential to carefully manage resources and their acquisition order. One practical approach is to ensure a consistent and predefined order for acquiring locks. By avoiding circular wait and ensuring a consistent lock ordering, deadlocks can be prevented.</p>
<p>Remember to always minimize lock contention and unnecessary locks. Additionally, utilize concurrency utilities such as <code>ReentrantLock</code> and <code>Semaphore</code> to manage locks effectively.</p>
<h3 id="heading-deadlock-example">Deadlock Example</h3>
<p>Complex deadlock scenarios involve intricate situations where multiple threads and resources are entangled, making detection and resolution more challenging. Let's explore an example to better understand this concept in the context of Java programming.</p>
<p>Consider the following code snippet that demonstrates a potential deadlock scenario:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockExample</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object resource1 = <span class="hljs-keyword">new</span> Object();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object resource2 = <span class="hljs-keyword">new</span> Object();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object resource3 = <span class="hljs-keyword">new</span> Object();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource1) {
            <span class="hljs-comment">// Perform operations with resource1</span>
            <span class="hljs-keyword">synchronized</span> (resource2) {
                <span class="hljs-comment">// Perform operations with resource2</span>
                <span class="hljs-keyword">synchronized</span> (resource3) {
                    <span class="hljs-comment">// Perform operations with resource3</span>
                }
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource3) {
            <span class="hljs-comment">// Perform operations with resource3</span>
            <span class="hljs-keyword">synchronized</span> (resource2) {
                <span class="hljs-comment">// Perform operations with resource2</span>
                <span class="hljs-keyword">synchronized</span> (resource1) {
                    <span class="hljs-comment">// Perform operations with resource1</span>
                }
            }
        }
    }
}
</code></pre>
<p>In this example, three threads, let's call them Thread A, Thread B, and Thread C, call <code>method1</code> and <code>method2</code> concurrently. If Thread A acquires <code>resource1</code> and waits for <code>resource2</code>, Thread B acquires <code>resource2</code> and waits for <code>resource3</code>, and Thread C acquires <code>resource3</code> and waits for <code>resource1</code>, a complex deadlock occurs. All threads are stuck in a state of indefinite waiting, unable to proceed.</p>
<p>To avoid such complex deadlocks, it becomes even more crucial to carefully manage resources and their acquisition order. </p>
<p>One practical approach is to establish a consistent and predefined order for acquiring locks. By doing so, we can prevent circular wait conditions and ensure a smooth execution of concurrent code.</p>
<p>To solve this issue, you need to ensure that all methods acquire the locks in the same order. Here’s the corrected code:</p>
<pre><code><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockExample</span> </span>{
    private <span class="hljs-keyword">static</span> final <span class="hljs-built_in">Object</span> resource1 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Object</span>();
    private <span class="hljs-keyword">static</span> final <span class="hljs-built_in">Object</span> resource2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Object</span>();
    private <span class="hljs-keyword">static</span> final <span class="hljs-built_in">Object</span> resource3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Object</span>();

    public <span class="hljs-keyword">void</span> method1() {
        synchronized (resource1) {
            <span class="hljs-comment">// Perform operations with resource1</span>
            synchronized (resource2) {
                <span class="hljs-comment">// Perform operations with resource2</span>
                synchronized (resource3) {
                    <span class="hljs-comment">// Perform operations with resource3</span>
                }
            }
        }
    }

    public <span class="hljs-keyword">void</span> method2() {
        synchronized (resource1) {
            <span class="hljs-comment">// Perform operations with resource1</span>
            synchronized (resource2) {
                <span class="hljs-comment">// Perform operations with resource2</span>
                synchronized (resource3) {
                    <span class="hljs-comment">// Perform operations with resource3</span>
                }
            }
        }
    }
}
</code></pre><p>In this corrected code, both <code>method1</code> and <code>method2</code> acquire locks on <code>resource1</code>, <code>resource2</code>, and <code>resource3</code> in the same order, which prevents the deadlock. This strategy is known as <strong>lock ordering</strong> — a simple yet effective way to prevent deadlocks. </p>
<p>It’s a good practice to always acquire locks in the same order throughout your program. This way, if a thread holds one lock and requests another, you can be sure that no other threads are holding or requesting locks in the opposite order. This eliminates the circular wait condition, and thus, the deadlock. </p>
<p>Remember, the order of releasing the locks doesn’t matter in preventing deadlocks. It’s the order of acquiring locks that’s crucial.</p>
<p>To resolve the potential deadlock in the provided example, we can modify the order of acquiring locks in either <code>method1</code> or <code>method2</code>. By consistently acquiring resources in the same order across all methods, we eliminate the possibility of circular wait and mitigate the risk of deadlock.</p>
<h3 id="heading-how-to-detect-and-analyze-deadlocks">How to Detect and Analyze Deadlocks</h3>
<p>To detect deadlocks in Java, you can analyze thread dumps. Thread dumps provide valuable information about the state of threads, including their locks and waiting conditions. By carefully examining the thread dump, you can identify if any threads are stuck in a deadlock situation.</p>
<p>One useful tool for deadlock detection is the <code>jstack</code> command. This command allows you to generate a thread dump of a Java application. You can then analyze the thread dump to identify any potential deadlocks.</p>
<p>Here's an example of how you can use the <code>jstack</code> command to detect deadlocks in a Java application:</p>
<pre><code class="lang-java">$ jstack &lt;pid&gt;
</code></pre>
<p>In this command, <code>&lt;pid&gt;</code> represents the process ID of the Java application. By running this command, you will obtain a thread dump that can be analyzed for deadlock situations.</p>
<p>By being proactive in detecting deadlocks and utilizing tools like <code>jstack</code>, you can quickly identify and address potential issues in your Java code.</p>
<p>Remember, when it comes to deadlocks, prevention is key. Be mindful of your resource acquisition order and avoid circular wait conditions. Additionally, consider using concurrency utilities like <code>ReentrantLock</code> and <code>Semaphore</code> to manage locks effectively.</p>
<h3 id="heading-how-to-resolve-deadlocks">How to Resolve Deadlocks</h3>
<p>To resolve deadlocks, there are two main strategies you can employ: breaking the deadlock cycle and refactoring the code to eliminate circular wait conditions.</p>
<p>Breaking the deadlock cycle involves identifying the resources involved in the deadlock and implementing a strategy to break the cycle. </p>
<p>One approach is to define a global ordering of resources and ensure that all threads acquire resources in the same order. By doing so, you eliminate the possibility of circular wait and allow the threads to proceed without deadlock. </p>
<p>Here's an example of how you can break the deadlock cycle:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockResolver</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object resource1 = <span class="hljs-keyword">new</span> Object();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object resource2 = <span class="hljs-keyword">new</span> Object();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource1) {
            <span class="hljs-comment">// Do something with resource1</span>
            <span class="hljs-keyword">synchronized</span> (resource2) {
                <span class="hljs-comment">// Do something with resource2</span>
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource1) {
            <span class="hljs-comment">// Do something with resource1</span>
            <span class="hljs-keyword">synchronized</span> (resource2) {
                <span class="hljs-comment">// Do something with resource2</span>
            }
        }
    }
}
</code></pre>
<p>In this example, we have modified the code to ensure that both <code>method1</code> and <code>method2</code> acquire resources in the same order: <code>resource1</code> followed by <code>resource2</code>. By maintaining this consistent lock ordering across all methods, we break the deadlock cycle and allow the threads to execute without deadlock.</p>
<p>Another strategy is to refactor the code to eliminate circular wait conditions. This involves restructuring the code to remove the dependency between resources that leads to deadlock. By carefully analyzing the resource dependencies and redesigning the code, you can eliminate the possibility of circular wait and prevent deadlocks. </p>
<p>Here's an example:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockResolver</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object resource1 = <span class="hljs-keyword">new</span> Object();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object resource2 = <span class="hljs-keyword">new</span> Object();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource1) {
            <span class="hljs-comment">// Do something with resource1</span>
        }
        <span class="hljs-keyword">synchronized</span> (resource2) {
            <span class="hljs-comment">// Do something with resource2</span>
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource1) {
            <span class="hljs-comment">// Do something with resource1</span>
        }
        <span class="hljs-keyword">synchronized</span> (resource2) {
            <span class="hljs-comment">// Do something with resource2</span>
        }
    }
}
</code></pre>
<p>In this refactored code, we have removed the nested locks and ensured that each resource is acquired and released independently. By doing so, we eliminate the possibility of circular wait and mitigate the risk of deadlock.</p>
<h3 id="heading-how-to-prevent-deadlocks">How to Prevent Deadlocks</h3>
<h4 id="heading-avoiding-nested-locks">Avoiding Nested Locks:</h4>
<p>To prevent deadlock conditions, avoid using nested locks in your code. Nested locks occur when a thread acquires a lock while holding another lock. This can lead to a situation where multiple threads are waiting for each other to release the locks they hold, resulting in a deadlock.</p>
<p>Instead of using nested locks, consider restructuring your code to acquire locks in a more organized and controlled manner. By acquiring locks one at a time and releasing them promptly, you can minimize the chances of deadlocks occurring. Let's take a look at an example:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockPreventionExample</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object lock1 = <span class="hljs-keyword">new</span> Object();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object lock2 = <span class="hljs-keyword">new</span> Object();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (lock1) {
            <span class="hljs-comment">// Perform operations with lock1</span>
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (lock2) {
            <span class="hljs-comment">// Perform operations with lock2</span>
        }
    }
}
</code></pre>
<p>In this example, the code has been refactored to eliminate nested locks. Each method now acquires and releases a single lock independently. This approach ensures that threads can execute their operations without getting stuck in a deadlock situation.</p>
<h4 id="heading-lock-ordering">Lock Ordering:</h4>
<p>Consistent ordering of lock acquisition is another effective technique to prevent deadlocks. By establishing a predefined order for acquiring locks across all threads, you eliminate the possibility of circular wait conditions.</p>
<p>When designing your code, carefully analyze the dependencies between resources and determine a logical order for acquiring locks. By consistently following this order, you ensure that threads acquire locks in a predictable manner, minimizing the risk of deadlocks.</p>
<p>Consider the following example:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockPreventionExample</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object lock1 = <span class="hljs-keyword">new</span> Object();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object lock2 = <span class="hljs-keyword">new</span> Object();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (lock1) {
            <span class="hljs-comment">// Perform operations with lock1</span>
            <span class="hljs-keyword">synchronized</span> (lock2) {
                <span class="hljs-comment">// Perform operations with lock2</span>
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (lock1) {
            <span class="hljs-comment">// Perform operations with lock1</span>
            <span class="hljs-keyword">synchronized</span> (lock2) {
                <span class="hljs-comment">// Perform operations with lock2</span>
            }
        }
    }
}
</code></pre>
<p>In this code snippet, both <code>method1</code> and <code>method2</code> acquire locks in the same order: first <code>lock1</code> and then <code>lock2</code>. By consistently following this lock acquisition order across all methods, you eliminate the possibility of circular wait conditions and ensure a smooth execution of concurrent code.</p>
<h4 id="heading-timeouts-and-try-lock">Timeouts and Try-Lock:</h4>
<p>Using timeouts and try-lock mechanisms can help you avoid indefinite waiting, which can potentially lead to deadlocks. </p>
<p>By setting a timeout on lock acquisition attempts or using try-lock methods, you can prevent threads from waiting indefinitely for a lock to become available.</p>
<p>Consider the following example:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockPreventionExample</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object lock1 = <span class="hljs-keyword">new</span> Object();
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Object lock2 = <span class="hljs-keyword">new</span> Object();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method1</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        <span class="hljs-keyword">if</span> (tryLock(lock1)) {
            <span class="hljs-keyword">try</span> {
                <span class="hljs-comment">// Perform operations with lock1</span>
                <span class="hljs-keyword">if</span> (tryLock(lock2)) {
                    <span class="hljs-keyword">try</span> {
                        <span class="hljs-comment">// Perform operations with lock2</span>
                    } <span class="hljs-keyword">finally</span> {
                        unlock(lock2);
                    }
                }
            } <span class="hljs-keyword">finally</span> {
                unlock(lock1);
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">method2</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        <span class="hljs-keyword">if</span> (tryLock(lock2)) {
            <span class="hljs-keyword">try</span> {
                <span class="hljs-comment">// Perform operations with lock2</span>
                <span class="hljs-keyword">if</span> (tryLock(lock1)) {
                    <span class="hljs-keyword">try</span> {
                        <span class="hljs-comment">// Perform operations with lock1</span>
                    } <span class="hljs-keyword">finally</span> {
                        unlock(lock1);
                    }
                }
            } <span class="hljs-keyword">finally</span> {
                unlock(lock2);
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">tryLock</span><span class="hljs-params">(Object lock)</span> <span class="hljs-keyword">throws</span> InterruptedException </span>{
        <span class="hljs-comment">// Attempt to acquire the lock with a timeout</span>
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">synchronized</span>(lock) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">unlock</span><span class="hljs-params">(Object lock)</span> </span>{
        <span class="hljs-keyword">synchronized</span>(lock) {
            <span class="hljs-comment">// Release the lock</span>
        }
    }
}
</code></pre>
<p>In this revised code, the methods <code>method1</code> and <code>method2</code> use a try-lock mechanism to acquire locks. If a lock is not immediately available, the thread does not wait indefinitely but proceeds to perform other operations. This approach helps prevent deadlocks by ensuring that threads do not get stuck waiting for locks indefinitely.</p>
<p>By following these practical techniques, such as avoiding nested locks, establishing consistent lock ordering, and utilizing timeouts and try-lock mechanisms, you can significantly reduce the risk of deadlocks in your Java multithreading code.</p>
<h3 id="heading-best-practices-for-avoiding-deadlocks">Best Practices for Avoiding Deadlocks</h3>
<p>To minimize lock contention and avoid unnecessary locks, it is important to follow best practices in Java multithreading. By using these techniques, you can improve the efficiency and performance of your concurrent code.</p>
<h4 id="heading-minimize-the-scope-of-locks">Minimize the Scope of Locks</h4>
<p>One effective practice is to minimize the scope of locks. Only synchronize the critical sections of code that require exclusive access to shared resources. By reducing the number of code blocks that are synchronized, you can minimize the chances of contention and improve the overall throughput.</p>
<h4 id="heading-use-thread-joins-wisely">Use Thread Joins Wisely</h4>
<p>Another useful practice is to use thread joins wisely. Thread joining is a mechanism that allows one thread to wait for the completion of another thread. </p>
<p>But it's important to be cautious when using thread joins, as incorrect usage can lead to deadlocks. Make sure to avoid situations where threads are waiting indefinitely for each other to complete, as this can result in a deadlock. Instead, carefully design your code to ensure proper synchronization and coordination between threads.</p>
<h4 id="heading-use-concurrency-utilities">Use Concurrency Utilities</h4>
<p>Java provides several concurrency utilities, such as <code>ReentrantLock</code>, <code>Semaphore</code>, and other synchronization classes, that can help manage locks effectively. These utilities offer more flexibility and control over locking mechanisms compared to traditional <code>synchronized</code> blocks. </p>
<p>For example, <code>ReentrantLock</code> allows for finer-grained locking and enables features like fairness and interruptibility. Similarly, <code>Semaphore</code> provides a convenient way to control access to shared resources by limiting the number of threads allowed to enter a critical section simultaneously.</p>
<p>Here's an example code snippet that demonstrates the use of <code>ReentrantLock</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.locks.ReentrantLock;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LockExample</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> ReentrantLock lock = <span class="hljs-keyword">new</span> ReentrantLock();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">performTask</span><span class="hljs-params">()</span> </span>{
        lock.lock();
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Critical section</span>
            <span class="hljs-comment">// Perform operations with shared resources</span>
        } <span class="hljs-keyword">finally</span> {
            lock.unlock();
        }
    }
}
</code></pre>
<p>In this example, the <code>ReentrantLock</code> is used to synchronize the critical section of code. By acquiring the lock before entering the critical section and releasing it afterward, you ensure exclusive access to shared resources.</p>
<h3 id="heading-advanced-deadlock-topics">Advanced Deadlock Topics</h3>
<p>Deadlocks can occur not only within a single JVM but also in distributed systems. It is important to broaden our understanding of deadlocks to include their occurrence in distributed environments. In such scenarios, multiple processes or nodes may compete for shared resources, leading to potential deadlocks.</p>
<p>To address deadlocks in distributed systems, it is crucial to carefully design the communication and coordination mechanisms between nodes. </p>
<p>One effective approach is to utilize message-based communication protocols, such as asynchronous messaging or event-driven architectures. These protocols can help minimize the chances of resource contention and reduce the risk of deadlocks.</p>
<p>Also, modern Java features and frameworks offer valuable tools to address deadlock and concurrency issues. </p>
<p>For example, the <code>CompletableFuture</code> class provides a convenient way to handle asynchronous computations and avoid blocking threads. By leveraging <code>CompletableFuture</code> and other similar features, you can ensure efficient and non-blocking execution of concurrent code.</p>
<p>Let's take a look at an example code snippet that demonstrates the use of <code>CompletableFuture</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.CompletableFuture;

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockAvoidanceExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> CompletableFuture&lt;String&gt; <span class="hljs-title">performTaskAsync</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> CompletableFuture.supplyAsync(() -&gt; {
            <span class="hljs-comment">// Perform asynchronous computations</span>
            <span class="hljs-keyword">return</span> <span class="hljs-string">"Result"</span>;
        });
    }
}
</code></pre>
<p>In this example, the CompletableFuture class is used to perform asynchronous computations. By using the <code>supplyAsync</code> method, you can execute the computations in a separate thread and obtain a <code>CompletableFuture</code> object that represents the result. This approach helps minimize the chances of deadlocks by avoiding the blocking of threads.</p>
<h2 id="heading-chapter-4-java-design-patterns">Chapter 4: Java Design Patterns</h2>
<p>Imagine you're an architect tasked with building a variety of houses, from simple one-bedroom homes to complex mansions with intricate designs. </p>
<p>Just like in architecture, where a set of blueprints offers proven solutions for building robust and aesthetically pleasing structures, Java Design Patterns provide software developers with time-tested methodologies and blueprints for crafting efficient and scalable software applications.</p>
<p>Why Java design patterns are still important in Software Development:</p>
<ol>
<li><strong>Universal Blueprint for Problem-Solving</strong>: Think of design patterns as the Swiss Army knife in a developer's toolkit. They are like those secret recipes that chefs pass down through generations – each pattern is a recipe for solving a specific design problem in a proven way.</li>
<li><strong>Timeless Relevance</strong>: Like the classic principles of art that never go out of style, Java Design Patterns have stood the test of time. They are like the underlying principles of physics that remain constant, irrespective of the evolving technological landscape.</li>
<li><strong>Enhances Communication</strong>: Using design patterns is akin to musicians using sheet music. They provide a universal language for developers. This shared vocabulary cuts through complexity, much like a well-drawn map simplifies navigation in unknown terrain.</li>
<li><strong>Principles of Good Design Embedded</strong>: These patterns are more than just templates – they are a manifestation of wisdom gathered over decades, much like the principles of good governance that stand the test of time in societies.</li>
<li><strong>Maintenance and Evolution</strong>: Imagine building with LEGO blocks. Design patterns allow software to be as adaptable and maintainable as rearranging LEGO structures, ensuring that systems can evolve gracefully as requirements change.</li>
</ol>
<h3 id="heading-overview-of-java-design-patterns">Overview of Java Design Patterns</h3>
<ol>
<li><strong>Singleton Pattern</strong>: Like a unique key to an exclusive club, this pattern ensures that there's only one instance of a class, providing a single point of access to it.</li>
<li><strong>Factory Method Pattern</strong>: Picture a master artisan who creates a template for an artifact. Subsequent artisans follow this template but add their unique touch, much like this pattern allows for creating objects with a common interface.</li>
<li><strong>Abstract Factory Pattern</strong>: This pattern is like a blueprint for a series of factories; each factory creates objects that, while different, share some common traits.</li>
<li><strong>Builder Pattern</strong>: Imagine a kit for building a model airplane. You can choose different parts for different versions of the plane. The Builder pattern lets you construct complex objects step-by-step, like using such a kit.</li>
<li><strong>Prototype Pattern</strong>: This is like having a master copy, and instead of building from scratch, you make duplicates of this master copy as needed.</li>
<li><strong>Adapter Pattern</strong>: Think of this as a travel adapter that lets you charge your phone anywhere in the world; the Adapter pattern allows otherwise incompatible interfaces to work together.</li>
<li><strong>Composite Pattern</strong>: Much like a painter who sees no difference between a single brushstroke and a complex mosaic, this pattern lets you treat individual objects and compositions uniformly.</li>
<li><strong>Proxy Pattern</strong>: Like a gatekeeper who controls access to a VIP, the Proxy pattern acts as an intermediary, controlling access to another object.</li>
<li><strong>Observer Pattern</strong>: It’s like a news alert service; whenever something newsworthy happens, you get notified. This pattern allows objects to notify others about changes in their state.</li>
<li><strong>Strategy Pattern</strong>: Imagine you’re a strategist in a game, constantly changing your tactics based on the situation. The Strategy pattern lets software change its algorithms dynamically, much like a strategist adapts their approach to shifting conditions on the battlefield.</li>
</ol>
<p>Each of these design patterns is a tool in the software developer's toolbox, ready to be deployed to tackle specific types of problems. By understanding and utilizing these patterns, developers can create software that is not only robust and efficient but also elegant and easy to maintain. </p>
<p>Just like the right tool can make a difficult task easy, the right design pattern can simplify complex coding challenges and lead to more effective and maintainable code. </p>
<p>Let's explore each of these patterns in more detail in the following sections, uncovering the secrets of their enduring power and versatility in the world of software development.</p>
<h3 id="heading-1-singleton-pattern">1. Singleton Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Singleton-Diagram-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Singleton pattern</em></p>
<p>The Singleton pattern addresses the problem of managing access to a resource that should have only one instance, such as a database connection. It ensures that only one instance of a class is created and provides a global access point to that instance. The Singleton pattern restricts object creation for a class to a single instance, which is managed by the class itself.</p>
<p>Singleton pattern is like having a key that unlocks a special treasure room. The key is unique and there can only be one key to access the treasure room. No matter how many people have the key, they all have access to the same treasure room. This ensures that everyone uses the same instance of the treasure room and prevents multiple instances from being created.</p>
<p>In Java, you can implement the Singleton pattern using a private constructor, a static method to return the instance, and a private static field to hold the single instance. Here's an example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Singleton</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> Singleton instance;

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-title">Singleton</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Private constructor to prevent instantiation</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> Singleton <span class="hljs-title">getInstance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
            <span class="hljs-keyword">synchronized</span> (Singleton.class) {
                <span class="hljs-keyword">if</span> (instance == <span class="hljs-keyword">null</span>) {
                    instance = <span class="hljs-keyword">new</span> Singleton();
                }
            }
        }
        <span class="hljs-keyword">return</span> instance;
    }

    <span class="hljs-comment">// Other methods and attributes...</span>
}
</code></pre>
<p>Using the Singleton pattern provides controlled access to the single instance, ensuring that all parts of the system use the same instance. However, it can be challenging to debug due to its global nature.</p>
<p>When using the Singleton pattern, consider its impact on a multi-threaded environment. Synchronization is necessary to make the <code>getInstance()</code> method thread-safe and prevent multiple instances from being created concurrently.</p>
<p>Keep in mind that design patterns are not strict rules to follow, but rather guidelines that can be adapted to fit your needs. Use them wisely and consider the trade-offs they entail in terms of complexity and maintainability.</p>
<h3 id="heading-2-factory-method-pattern">2. Factory Method Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Factory-Method-Pattern.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Factory Method pattern</em></p>
<p>The Factory Method pattern addresses the need for creating objects through an interface while allowing subclasses to determine the specific type of objects to be instantiated. It promotes loose coupling by delegating the responsibility of object creation to subclasses.</p>
<p>Imagine a scenario where different chefs are preparing their own versions of a dish. Each chef represents a subclass in the Factory Method pattern, and the dish represents the object being created. The interface acts as the recipe or guidelines for creating the dish.</p>
<p>Here's an example in Java:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Product</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">use</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteProductA</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Product</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">use</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Using ConcreteProductA"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteProductB</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Product</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">use</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Using ConcreteProductB"</span>);
    }
}

<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Creator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> Product <span class="hljs-title">createProduct</span><span class="hljs-params">()</span></span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doSomething</span><span class="hljs-params">()</span> </span>{
        Product product = createProduct();
        product.use();
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteCreatorA</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Creator</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">createProduct</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ConcreteProductA();
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteCreatorB</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Creator</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Product <span class="hljs-title">createProduct</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ConcreteProductB();
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Creator creatorA = <span class="hljs-keyword">new</span> ConcreteCreatorA();
        creatorA.doSomething(); <span class="hljs-comment">// Creating and using ConcreteProductA</span>

        Creator creatorB = <span class="hljs-keyword">new</span> ConcreteCreatorB();
        creatorB.doSomething(); <span class="hljs-comment">// Creating and using ConcreteProductB</span>
    }
}
</code></pre>
<p>In this example, the <code>Product</code> interface defines the method <code>use()</code>, which represents the behavior of the created objects. The <code>ConcreteProductA</code> and <code>ConcreteProductB</code> classes implement this interface and provide their own implementations of the <code>use()</code> method.</p>
<p>The <code>Creator</code> class is an abstract class that acts as the factory. It declares the <code>createProduct()</code> method, which is responsible for creating the specific type of product. The <code>doSomething()</code> method demonstrates how the factory method is used to create and use the product.</p>
<p>By using the Factory Method pattern, you gain flexibility in object creation. You can easily introduce new subclasses to create different types of products without modifying the existing code. But keep in mind that introducing too many subclasses can introduce complexity and make the code harder to maintain.</p>
<p>An analogy for the Factory Method pattern is like having a restaurant with different chefs specializing in various dishes. The restaurant provides the interface, specifying the general guidelines for creating the dishes. Each chef represents a subclass that creates their unique version of the dish based on the provided guidelines.</p>
<p>Design patterns are not strict rules to follow, but rather guidelines that can be adapted to fit your needs. Use them wisely, considering the trade-offs they entail in terms of complexity and maintainability.</p>
<h3 id="heading-3-abstract-factory-pattern">3. Abstract Factory Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Abstract-Factory-Pattern.png" alt="Image" width="600" height="400" loading="lazy">
<em>Abstract Factory pattern</em></p>
<p>The Abstract Factory pattern addresses the problem of creating families of related or dependent objects without specifying their concrete classes. It allows the creation of objects through interfaces, promoting consistency among products while allowing flexibility in their implementation.</p>
<p>Imagine different car factories producing various car models. Each factory represents a concrete factory in the Abstract Factory pattern, and the car models represent the related objects being created. The abstract factory acts as the blueprint or guidelines for creating these car models.</p>
<p>To implement the Abstract Factory pattern in Java, you can define an abstract factory interface that declares methods for creating the related objects. Each concrete factory implements this interface and provides its own implementation of the creation methods. The product interfaces represent the different types of objects that can be created by the factories.</p>
<p>Here's an example in Java:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">AbstractFactory</span> </span>{
    <span class="hljs-function">ProductA <span class="hljs-title">createProductA</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function">ProductB <span class="hljs-title">createProductB</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ProductA</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">use</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ProductB</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">consume</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteFactory1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">AbstractFactory</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ProductA <span class="hljs-title">createProductA</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ConcreteProductA1();
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ProductB <span class="hljs-title">createProductB</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ConcreteProductB1();
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteFactory2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">AbstractFactory</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ProductA <span class="hljs-title">createProductA</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ConcreteProductA2();
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ProductB <span class="hljs-title">createProductB</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> ConcreteProductB2();
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteProductA1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ProductA</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">use</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Using ConcreteProductA1"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteProductA2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ProductA</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">use</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Using ConcreteProductA2"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteProductB1</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ProductB</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">consume</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Consuming ConcreteProductB1"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteProductB2</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ProductB</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">consume</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Consuming ConcreteProductB2"</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        AbstractFactory factory1 = <span class="hljs-keyword">new</span> ConcreteFactory1();
        ProductA productA1 = factory1.createProductA();
        productA1.use(); <span class="hljs-comment">// Using ConcreteProductA1</span>
        ProductB productB1 = factory1.createProductB();
        productB1.consume(); <span class="hljs-comment">// Consuming ConcreteProductB1</span>

        AbstractFactory factory2 = <span class="hljs-keyword">new</span> ConcreteFactory2();
        ProductA productA2 = factory2.createProductA();
        productA2.use(); <span class="hljs-comment">// Using ConcreteProductA2</span>
        ProductB productB2 = factory2.createProductB();
        productB2.consume(); <span class="hljs-comment">// Consuming ConcreteProductB2</span>
    }
}
</code></pre>
<p>In this example, the <code>AbstractFactory</code> interface declares methods for creating <code>ProductA</code> and <code>ProductB</code> objects. The <code>ConcreteFactory1</code> and <code>ConcreteFactory2</code> classes implement this interface and provide their own implementations of the creation methods.</p>
<p>The <code>ProductA</code> and <code>ProductB</code> interfaces represent the different types of objects that can be created by the factories. The <code>ConcreteProductA1</code>, <code>ConcreteProductA2</code>, <code>ConcreteProductB1</code>, and <code>ConcreteProductB2</code> classes implement these interfaces and provide their own implementations of the behavior.</p>
<p>By using the Abstract Factory pattern, you can create families of related objects without specifying their concrete classes. This promotes consistency among the created objects and allows for easy interchangeability between different implementations. But keep in mind that introducing too many concrete factories and products can increase complexity, so use this pattern judiciously.</p>
<h3 id="heading-4-builder-pattern">4. Builder Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Builder-Pattern.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Builder pattern</em></p>
<p>The Builder pattern is a creational design pattern that solves the problem of creating complex objects with multiple parts and configurations. It separates the construction of an object from its representation, allowing step-by-step creation of complex objects.</p>
<p>Imagine building a house with different construction plans. Each plan represents a concrete builder in the Builder pattern, and the house represents the complex object being created. The director acts as the blueprint or guidelines for constructing the house.</p>
<p>To implement the Builder pattern in Java, you can define a builder interface that declares methods for building different parts of the object. Each concrete builder implements this interface and provides its own implementation of the construction methods. The director class coordinates the construction process by invoking the builder's methods.</p>
<p>Here's an example in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Builder</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">buildPart1</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">buildPart2</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">buildPart3</span><span class="hljs-params">()</span></span>;
    <span class="hljs-comment">// Other construction methods...</span>

    <span class="hljs-function">ComplexObject <span class="hljs-title">getResult</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteBuilder</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Builder</span> </span>{
    <span class="hljs-keyword">private</span> ComplexObject complexObject;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ConcreteBuilder</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">this</span>.complexObject = <span class="hljs-keyword">new</span> ComplexObject();
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildPart1</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Build part 1 of the complex object</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildPart2</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Build part 2 of the complex object</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">buildPart3</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Build part 3 of the complex object</span>
    }

    <span class="hljs-comment">// Implement other construction methods...</span>

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> ComplexObject <span class="hljs-title">getResult</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.complexObject;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Director</span> </span>{
    <span class="hljs-keyword">private</span> Builder builder;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Director</span><span class="hljs-params">(Builder builder)</span> </span>{
        <span class="hljs-keyword">this</span>.builder = builder;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">construct</span><span class="hljs-params">()</span> </span>{
        builder.buildPart1();
        builder.buildPart2();
        builder.buildPart3();
        <span class="hljs-comment">// Call other construction methods...</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ComplexObject</span> </span>{
    <span class="hljs-comment">// Define the complex object with its parts and configurations</span>
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Builder builder = <span class="hljs-keyword">new</span> ConcreteBuilder();
        Director director = <span class="hljs-keyword">new</span> Director(builder);

        director.construct();

        ComplexObject complexObject = builder.getResult();
        <span class="hljs-comment">// Use the constructed complex object</span>
    }
}
</code></pre>
<p>In this example, the <code>Builder</code> interface declares methods for building different parts of the complex object. The <code>ConcreteBuilder</code> class implements this interface and provides its own implementation of the construction methods. The <code>Director</code> class coordinates the construction process by invoking the builder's methods in a specific order.</p>
<p>By using the Builder pattern, you have more control over the construction of complex objects, allowing you to build them step by step. This pattern is particularly useful when creating objects with many optional or varied parts. However, keep in mind that introducing too many builders can increase complexity, so use this pattern judiciously.</p>
<h3 id="heading-5-prototype-pattern">5. Prototype Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/PrototypePattern.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Prototype pattern</em></p>
<p>The Prototype pattern addresses the need for copying or cloning objects instead of creating new instances. It allows for the creation of new objects by copying an existing object, utilizing a prototype instance. This pattern consists of a prototype interface and concrete prototypes that implement the interface.</p>
<p>To understand the Prototype pattern, think of it as making photocopies of a document. The original document serves as the prototype, and the copies are created by simply duplicating the original. Similarly, the Prototype pattern allows for efficient cloning of objects by utilizing an existing instance as a blueprint for creating new instances.</p>
<p>In Java, you can implement the Prototype pattern by defining a prototype interface that declares a method for cloning the object. Each concrete prototype class then implements this interface and provides its own implementation of the cloning method. Here's an example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Prototype</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Cloneable</span> </span>{
    <span class="hljs-function">Prototype <span class="hljs-title">clone</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcretePrototype</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Prototype</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Prototype <span class="hljs-title">clone</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">return</span> (Prototype) <span class="hljs-keyword">super</span>.clone();
        } <span class="hljs-keyword">catch</span> (CloneNotSupportedException e) {
            <span class="hljs-comment">// Handle clone exception</span>
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Prototype prototype = <span class="hljs-keyword">new</span> ConcretePrototype();
        Prototype clone = prototype.clone();
        <span class="hljs-comment">// Use the cloned object</span>
    }
}
</code></pre>
<p>In this example, the <code>Prototype</code> interface declares the <code>clone()</code> method for cloning the object. The <code>ConcretePrototype</code> class implements this interface and overrides the <code>clone()</code> method to perform a shallow copy of the object. The <code>Main</code> class demonstrates how to use the Prototype pattern by creating a concrete prototype and cloning it to obtain a new instance.</p>
<p>When using the Prototype pattern, keep in mind that the cloning process can become complex when involving deep cloning, where all the object's references are also cloned. It's important to handle any clone exceptions that may occur.</p>
<h3 id="heading-6-adapter-pattern">6. Adapter Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Adapter-Pattern.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Adaptor pattern</em></p>
<p>The Adapter pattern solves the problem of incompatible interfaces between classes, allowing them to collaborate effectively. It achieves this by adapting one interface to another using a middle layer called the adapter. The components involved in this pattern are the Adapter, Adaptee, and Target interface.</p>
<p>To understand the Adapter pattern, consider power socket adapters for different country plugs. The adapter serves as a bridge between the incompatible plug and the socket, allowing them to work together. </p>
<p>Similarly, the Adapter pattern enables collaboration between classes with incompatible interfaces by providing a common interface through the adapter.</p>
<p>Here's an example of how the Adapter pattern can be implemented in Java:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Adaptee interface</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">LegacyCode</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">legacyMethod</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Adaptee implementation</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LegacyCodeImpl</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">LegacyCode</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">legacyMethod</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Implementation of legacy method</span>
    }
}

<span class="hljs-comment">// Target interface</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">NewCode</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">newMethod</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Adapter implementation</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Adapter</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">NewCode</span> </span>{
    <span class="hljs-keyword">private</span> LegacyCode legacyCode;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Adapter</span><span class="hljs-params">(LegacyCode legacyCode)</span> </span>{
        <span class="hljs-keyword">this</span>.legacyCode = legacyCode;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">newMethod</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Adapt the new method to the legacy code</span>
        legacyCode.legacyMethod();
    }
}

<span class="hljs-comment">// Client code</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        LegacyCode legacyCode = <span class="hljs-keyword">new</span> LegacyCodeImpl();
        NewCode newCode = <span class="hljs-keyword">new</span> Adapter(legacyCode);
        newCode.newMethod();
    }
}
</code></pre>
<p>In this example, the <code>LegacyCode</code> interface represents the existing code with its own legacy method. The <code>LegacyCodeImpl</code> class implements this interface and provides the implementation of the legacy method.</p>
<p>The <code>NewCode</code> interface represents the desired new interface for the client code. The <code>Adapter</code> class implements this interface and contains a reference to the <code>LegacyCode</code> object. It adapts the new method to the existing legacy code by invoking the legacy method inside the new method.</p>
<p>By using the Adapter pattern, you can integrate legacy code or collaborate with classes that have incompatible interfaces. The adapter acts as a translator, enabling communication between the different components. Remember to choose meaningful names for the classes and interfaces to improve code readability.</p>
<p>When applying the Adapter pattern, consider the trade-offs it entails. While it allows collaboration between incompatible interfaces, it introduces an additional layer of complexity. Use this pattern judiciously and consider the specific needs of your project.</p>
<h3 id="heading-7-composite-pattern">7. Composite Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Compositepattern.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Composite pattern</em></p>
<p>The Composite pattern addresses the problem of treating individual objects and compositions of objects uniformly. It allows us to create tree-like structures to represent part-whole hierarchies.</p>
<p>In this pattern, we have two types of objects: composite objects and leaf objects. Composite objects can contain other objects, including both composite objects and leaf objects. Leaf objects, on the other hand, are the building blocks of the hierarchy and cannot contain other objects.</p>
<p>To understand this pattern, imagine a file system where we have nested folders. The folders represent composite objects, while the files represent leaf objects. By treating folders and files uniformly, we can perform operations on them regardless of their specific type.</p>
<p>Here's an example implementation in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Component</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">operation</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Composite</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Component</span> </span>{
    <span class="hljs-keyword">private</span> List&lt;Component&gt; children = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">add</span><span class="hljs-params">(Component component)</span> </span>{
        children.add(component);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">remove</span><span class="hljs-params">(Component component)</span> </span>{
        children.remove(component);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">operation</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">for</span> (Component component : children) {
            component.operation();
        }
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Leaf</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Component</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">operation</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Perform the operation on the leaf object</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Composite composite = <span class="hljs-keyword">new</span> Composite();
        composite.add(<span class="hljs-keyword">new</span> Leaf());
        composite.add(<span class="hljs-keyword">new</span> Leaf());

        composite.operation(); <span class="hljs-comment">// Perform the operation on the composite object and its children</span>
    }
}
</code></pre>
<p>In this example, the <code>Component</code> interface declares the <code>operation()</code> method that represents the operation to be performed on both composite objects and leaf objects. The <code>Composite</code> class implements this interface and contains a list of child components. It provides methods to add and remove child components and overrides the <code>operation()</code> method to perform the operation on itself and its children.</p>
<p>The <code>Leaf</code> class also implements the <code>Component</code> interface and provides its own implementation of the <code>operation()</code> method.</p>
<p>By using the Composite pattern, we can simplify client code by treating individual objects and compositions of objects uniformly. But we should be cautious not to make the design overly general, as it may introduce unnecessary complexity.</p>
<h3 id="heading-8-proxy-pattern">8. Proxy Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/ProxyPattern-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Proxy pattern</em></p>
<p>The Proxy pattern is a structural design pattern that provides a placeholder for another object. It is used to control access to an object or delay its instantiation. A common example is a bank teller acting as a proxy for bank account transactions.</p>
<p>To understand the Proxy pattern, let's consider a scenario where we want to access a resource-intensive object, such as a large image or a remote database. Instead of directly accessing the object, we can use a proxy to control the access and provide additional functionality if needed.</p>
<p>In the Proxy pattern, we have three main components: the Proxy, the Subject interface, and the RealSubject. The Proxy class acts as a middleman between the client and the RealSubject. It controls access to the RealSubject and provides any additional logic or checks before delegating the request.</p>
<p>Here's an example implementation in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Subject</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">request</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RealSubject</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Subject</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">request</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Perform the actual request</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Proxy</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Subject</span> </span>{
    <span class="hljs-keyword">private</span> RealSubject realSubject;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">request</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span> (realSubject == <span class="hljs-keyword">null</span>) {
            realSubject = <span class="hljs-keyword">new</span> RealSubject();
        }

        <span class="hljs-comment">// Perform additional checks or logic before delegating the request</span>
        <span class="hljs-comment">// ...</span>

        realSubject.request();
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Client</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Subject subject = <span class="hljs-keyword">new</span> Proxy();
        subject.request();
    }
}
</code></pre>
<p>In this example, the Subject interface declares the common method for the request. The RealSubject class implements this interface and provides the actual implementation of the request. The Proxy class also implements the Subject interface and acts as a proxy for the RealSubject.</p>
<p>When the client makes a request through the Proxy, the Proxy checks if the RealSubject has been instantiated. If not, it creates an instance of the RealSubject. The Proxy can also perform additional checks or logic before delegating the request to the RealSubject.</p>
<p>The Proxy pattern provides several advantages, such as controlling access to the real object, delaying the instantiation of the real object until it is actually needed, and providing additional functionality or checks. But it can introduce latency due to the extra layer of indirection.</p>
<p>It's important to note that the Proxy pattern is different from the Adapter pattern, which is used to bridge incompatible interfaces. The Proxy acts as a placeholder or wrapper for the real object, while the Adapter provides a different interface for an existing object.</p>
<p>The Proxy pattern is a powerful tool for controlling access to objects or delaying their instantiation. By using a proxy, you can add extra functionality, perform checks, or provide a simplified interface for the client. Just be cautious of the potential latency introduced by the proxy.</p>
<h3 id="heading-9-observer-pattern">9. Observer Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/Add-a-subheading.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Observer pattern</em></p>
<p>The Composite pattern addresses the need to treat individual objects and compositions of objects uniformly, creating a tree-like structure to represent part-whole hierarchies. This pattern is useful when we want to perform operations on objects regardless of their specific type, such as in a file system where we have folders (composite objects) and files (leaf objects).</p>
<p>To implement the Composite pattern in Java, we can define a <code>Component</code> interface that declares an <code>operation()</code> method. The <code>Composite</code> class represents the composite object and maintains a list of child components. It provides methods to add and remove components, as well as an implementation of the <code>operation()</code> method that calls the <code>operation()</code> method on each child component. The <code>Leaf</code> class represents the leaf object and provides its own implementation of the <code>operation()</code> method.</p>
<p>Here's an example code snippet:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Component</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">operation</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Composite</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Component</span> </span>{
    <span class="hljs-keyword">private</span> List&lt;Component&gt; children = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">add</span><span class="hljs-params">(Component component)</span> </span>{
        children.add(component);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">remove</span><span class="hljs-params">(Component component)</span> </span>{
        children.remove(component);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">operation</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">for</span> (Component component : children) {
            component.operation();
        }
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Leaf</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Component</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">operation</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Perform the operation on the leaf object</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Composite composite = <span class="hljs-keyword">new</span> Composite();
        composite.add(<span class="hljs-keyword">new</span> Leaf());
        composite.add(<span class="hljs-keyword">new</span> Leaf());

        composite.operation(); <span class="hljs-comment">// Perform the operation on the composite object and its children</span>
    }
}
</code></pre>
<p>By using the Composite pattern, we can treat individual objects and compositions of objects uniformly, simplifying the code and providing flexibility. But it's important to note that adding too many levels of nesting can make the code more complex and harder to maintain. Therefore, it's important to strike the right balance and use this pattern judiciously.</p>
<h3 id="heading-10-strategy-pattern">10. Strategy Pattern</h3>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/strategypattern.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Strategy pattern</em></p>
<p>The Strategy pattern is a behavioral design pattern that allows for selecting algorithms or behaviors at runtime. It addresses the need to choose different strategies based on the situation, providing flexibility and interchangeability.</p>
<p>To understand the Strategy pattern, let's consider a real-world example of choosing transportation methods. Depending on the situation, we may need to select a car, a bike, or a bus. Each transportation method represents a strategy, and the situation represents the context.</p>
<p>In Java, we can implement the Strategy pattern by creating a Context class, a Strategy interface, and multiple ConcreteStrategy classes. The Context class encapsulates the algorithms or behaviors and provides a method to change the strategy at runtime. The Strategy interface defines the contract for the different strategies, and the ConcreteStrategy classes implement specific strategies.</p>
<p>Here's an example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Strategy</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">performAction</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteStrategyA</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Strategy</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">performAction</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Implement the strategy A</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConcreteStrategyB</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Strategy</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">performAction</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Implement the strategy B</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Context</span> </span>{
    <span class="hljs-keyword">private</span> Strategy strategy;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setStrategy</span><span class="hljs-params">(Strategy strategy)</span> </span>{
        <span class="hljs-keyword">this</span>.strategy = strategy;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">executeStrategy</span><span class="hljs-params">()</span> </span>{
        strategy.performAction();
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Context context = <span class="hljs-keyword">new</span> Context();

        context.setStrategy(<span class="hljs-keyword">new</span> ConcreteStrategyA());
        context.executeStrategy(); <span class="hljs-comment">// Perform strategy A</span>

        context.setStrategy(<span class="hljs-keyword">new</span> ConcreteStrategyB());
        context.executeStrategy(); <span class="hljs-comment">// Perform strategy B</span>
    }
}
</code></pre>
<p>In this example, the <code>Strategy</code> interface declares the <code>performAction()</code> method, which represents the behavior of the different strategies. The <code>ConcreteStrategyA</code> and <code>ConcreteStrategyB</code> classes implement this interface and provide their own implementations of the strategies.</p>
<p>The <code>Context</code> class holds a reference to the current strategy and provides methods to set the strategy and execute it. By changing the strategy at runtime, we can easily switch between different behaviors.</p>
<p>When using the Strategy pattern, it's essential to identify the problem and choose the appropriate strategies. Consider the advantages and trade-offs, such as flexibility and potential complexity due to multiple strategy classes.</p>
<h2 id="heading-chapter-5-how-to-optimize-java-code-for-speed-and-efficiency">Chapter 5: How to Optimize Java Code for Speed and Efficiency</h2>
<p>Java optimization is a crucial aspect of developing high-performance applications. In this guide, we will explore the various techniques and tools that can help improve the speed and efficiency of your Java code.</p>
<p>When it comes to understanding Java performance, it is essential to grasp the basics. You should be familiar with key performance metrics and be able to identify common performance bottlenecks. By analyzing and addressing these bottlenecks, you can significantly enhance the overall performance of your application.</p>
<p>One effective way to optimize your Java code is through computational optimization. This involves using efficient data structures and algorithms to reduce CPU cycle consumption. By carefully selecting the right algorithms and optimizing their implementation, you can achieve significant performance improvements.</p>
<p>Another important aspect of Java optimization is resource conflict optimization. This involves managing multi-threaded environments and implementing synchronization and locking mechanisms appropriately. By ensuring proper coordination among threads, you can avoid conflicts and improve the efficiency of your code.</p>
<p>Additionally, JVM optimization plays a crucial role in enhancing Java performance. By tuning JVM parameters and configuring garbage collectors, you can optimize memory usage and reduce overhead. Understanding the behavior of garbage collection and leveraging profiling and benchmarking techniques can further aid in optimizing your Java code.</p>
<p>To assist you in the optimization process, there are various tools available. Code analysis tools can help identify potential issues and provide suggestions for improvement. Tools for garbage collection analysis, continuous profiling, JIT compilation analysis, benchmarking, and real-time monitoring can also be valuable in identifying performance bottlenecks and optimizing your code.</p>
<p>In order to achieve the best results, it is important to follow best practices in Java optimization. Writing clean and maintainable code, avoiding common pitfalls, and implementing efficient memory management strategies are essential.</p>
<p>Throughout this chapter, we will explore real-world case studies and provide practical advice based on experience. We will also touch upon advanced topics such as optimizing Java in cloud environments and Java performance in microservices architecture.</p>
<p>By applying these techniques and insights, you can optimize your Java code for speed and efficiency, leading to enhanced performance and better user experiences.</p>
<h3 id="heading-java-optimization-techniques">Java Optimization Techniques</h3>
<p>When it comes to optimizing your Java code, there are several key areas to focus on: computational optimization, resource conflict optimization, algorithm code optimization, and JVM optimization.</p>
<h4 id="heading-computational-optimization">Computational optimization</h4>
<p>In computational optimization, one effective approach is to utilize efficient data structures and algorithms. </p>
<p>By carefully selecting the right data structures and algorithms for your specific use case, you can significantly reduce CPU cycle consumption and improve the overall performance of your code. </p>
<p>Let's take a look at an example:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Example code demonstrating efficient data structures and algorithms</span>
List&lt;String&gt; names = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
names.add(<span class="hljs-string">"John"</span>);
names.add(<span class="hljs-string">"Jane"</span>);
names.add(<span class="hljs-string">"Michael"</span>);

<span class="hljs-keyword">for</span> (String name : names) {
    System.out.println(name);
}
</code></pre>
<h4 id="heading-resource-conflict-optimization">Resource conflict optimization</h4>
<p>In resource conflict optimization, it is crucial to effectively manage multi-threaded environments and implement synchronization and locking mechanisms. </p>
<p>By ensuring proper coordination among threads, you can avoid conflicts and enhance the efficiency of your code. </p>
<p>Here's an example to illustrate this concept:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Example code demonstrating resource conflict optimization</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> count = <span class="hljs-number">0</span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">void</span> <span class="hljs-title">increment</span><span class="hljs-params">()</span> </span>{
        count++;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">synchronized</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getCount</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> count;
    }
}
</code></pre>
<h4 id="heading-algorithm-code-optimization">Algorithm code optimization</h4>
<p>Algorithm code optimization involves selecting the right algorithms and leveraging profiling and benchmarking techniques. </p>
<p>By analyzing the performance characteristics of different algorithms and fine-tuning their implementation, you can achieve significant performance improvements. </p>
<p>Here's an example:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Example code demonstrating algorithm code optimization</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ArrayUtils</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">findMax</span><span class="hljs-params">(<span class="hljs-keyword">int</span>[] arr)</span> </span>{
        <span class="hljs-keyword">int</span> max = Integer.MIN_VALUE;
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : arr) {
            <span class="hljs-keyword">if</span> (num &gt; max) {
                max = num;
            }
        }
        <span class="hljs-keyword">return</span> max;
    }
}
</code></pre>
<h4 id="heading-jvm-optimization">JVM Optimization</h4>
<p>JVM optimization plays a crucial role in enhancing Java performance. By tuning JVM parameters and configuring garbage collectors, you can optimize memory usage and reduce overhead. </p>
<p>It is essential to understand the behavior of garbage collection and leverage profiling and benchmarking techniques to fine-tune your Java code. Remember, JVM optimization can have a significant impact on the overall performance of your application.</p>
<p>By focusing on these key areas of optimization and applying the techniques discussed, you can greatly improve the speed and efficiency of your Java code. </p>
<h3 id="heading-java-optimization-tools">Java Optimization Tools</h3>
<p>When it comes to optimizing your Java code, several key tools deserve your attention. Let's delve into each of them and explore practical advice to improve performance.</p>
<h4 id="heading-code-analysis-tools-like-checkstyle-pmd-and-findbugs-now-spotbugs">Code Analysis Tools like Checkstyle, PMD, and FindBugs (now SpotBugs).</h4>
<p><strong>Application:</strong> These tools statically analyze your Java code to catch style discrepancies, potential bugs, and anti-patterns. </p>
<p>For instance, Checkstyle can enforce a coding standard by checking for deviations from preset rules. PMD finds common programming flaws like unused variables, empty catch blocks, unnecessary object creation, and so on. SpotBugs scans for instances of bug patterns/potential errors that are likely to lead to runtime errors or incorrect behavior.</p>
<h4 id="heading-garbage-collection-analysis-tools-like-visualvm-gcviewer-and-jclaritys-censum">Garbage Collection Analysis Tools like VisualVM, GCViewer, and JClarity's Censum.</h4>
<p><strong>Application:</strong> These tools help in analyzing Java heap dumps and garbage collection logs. </p>
<p>VisualVM can attach to a running JVM and monitor object creation and garbage collection, which helps in tuning the heap size and selecting the appropriate garbage collector. GCViewer can read JVM garbage collection logs to visualize and analyze garbage collection processes. Censum can interpret verbose garbage collection logs to recommend optimizations.</p>
<h4 id="heading-continuous-profiling-tools-like-yourkit-jprofiler-and-java-flight-recorder-jfr">Continuous Profiling Tools like YourKit, JProfiler, and Java Flight Recorder (JFR).</h4>
<p><strong>Application:</strong> Continuous profiling tools are used to identify performance issues in a running Java application. </p>
<p>YourKit provides powerful on-demand profiling of both CPU and memory usage, as well as extensive analysis capabilities. JProfiler offers a live profiling of a local or remote session, and can track down performance bottlenecks, memory leaks, and threading issues. Java Flight Recorder, part of the JDK, collects detailed runtime information about the JVM which can be analyzed later.</p>
<h4 id="heading-jit-compilation-analysis-tools-like-jitwatch-oracle-solaris-studio-performance-analyzer">JIT Compilation Analysis Tools like JITWatch, Oracle Solaris Studio Performance Analyzer.</h4>
<p><strong>Application:</strong> These tools help developers understand the intricacies of the JIT compiler.</p>
<p> JITWatch is a tool that analyzes the Just-In-Time (JIT) compilation process of the HotSpot JVM. It visualizes the compiler optimizations and provides feedback on how the JIT compiler is translating bytecode into machine code. The Performance Analyzer can track the performance of applications and can show how code is being executed, allowing developers to see which methods are being JIT-compiled and how often.</p>
<h4 id="heading-benchmarking-tools-like-jmh-java-microbenchmark-harness-google-caliper">Benchmarking Tools like JMH (Java Microbenchmark Harness), Google Caliper.</h4>
<p><strong>Application:</strong> Benchmarking tools like JMH are designed for benchmarking code sections (usually methods) to measure their performance. </p>
<p>JMH is specifically tailored for Java and other JVM languages and allows you to define a benchmarking job and measure its performance under different conditions. Google Caliper is another benchmarking framework that's designed to help you record, analyze, and compare the performance of your Java code.</p>
<h4 id="heading-monitoring-tools-like-nagios-prometheus-with-jmx-exporter-and-new-relic">Monitoring Tools like Nagios, Prometheus with JMX exporter, and New Relic.</h4>
<p><strong>Application:</strong> These tools are used for the real-time monitoring of Java applications. </p>
<p>Nagios can monitor JVM metrics and provide alerts based on thresholds. Prometheus can scrape metrics exposed by JVM using JMX exporter and allows for powerful querying. New Relic provides an APM (Application Performance Management) tool that offers real-time insights into your application's operation, with detailed transaction traces, error tracking, and application topology mapping.</p>
<p>Let's look at how you can use each type of tool to better optimize your Java code.</p>
<h3 id="heading-how-to-use-code-analysis-tools">How to Use Code Analysis Tools</h3>
<p>Static code analysis plays a crucial role in identifying potential issues and suggesting improvements in your Java code. By utilizing popular Java code analysis tools, you can gain valuable insights into code quality and ensure adherence to best practices.</p>
<p><strong>Static Code Analysis Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Example code demonstrating static code analysis</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">User</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printUserInfo</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Name: "</span> + name);
        System.out.println(<span class="hljs-string">"Age: "</span> + age);
    }
}
</code></pre>
<h3 id="heading-how-to-use-garbage-collection-analysis-tools">How to Use Garbage Collection Analysis Tools</h3>
<p>Understanding garbage collection in Java is essential for optimizing memory usage and reducing overhead. By employing tools specifically designed for analyzing garbage collection behavior, you can fine-tune your Java code and optimize memory allocation.</p>
<p><strong>Garbage Collection Analysis Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Example code demonstrating garbage collection analysis</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MemoryIntensiveTask</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        List&lt;Integer&gt; numbers = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000000</span>; i++) {
            numbers.add(i);
        }
        <span class="hljs-comment">// Perform memory-intensive operations</span>
        <span class="hljs-comment">// ...</span>
        numbers.clear();
    }
}
</code></pre>
<h3 id="heading-how-to-use-continuous-profiling-tools">How to Use Continuous Profiling Tools</h3>
<p>Continuous profiling enables you to gather real-time performance data and identify performance bottlenecks in your Java application. By using recommended profiling tools, you can gain insights into CPU usage, memory allocation, and method-level performance, allowing you to make targeted optimizations.</p>
<p><strong>Continuous Profiling Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Example code demonstrating continuous profiling</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PerformanceAnalyzer</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Start profiling</span>
        Profiler.start();

        <span class="hljs-comment">// Perform operations to analyze performance</span>
        <span class="hljs-comment">// ...</span>

        <span class="hljs-comment">// Stop profiling and print performance report</span>
        Profiler.stop();
        Profiler.printReport();
    }
}
</code></pre>
<h3 id="heading-how-to-use-jit-compilation-analysis-tools">How to Use JIT Compilation Analysis Tools</h3>
<p>Just-in-time (JIT) compilation is a crucial component of Java performance. Exploring JIT compilation behavior through dedicated tools allows you to understand how your code is optimized at runtime. By analyzing JIT compilation, you can make informed decisions to improve performance.</p>
<p><strong>JIT Compilation Analysis Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Example code demonstrating JIT compilation analysis</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LoopExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; <span class="hljs-number">1000</span>; i++) {
            System.out.println(<span class="hljs-string">"Iteration: "</span> + i);
        }
    }
}
</code></pre>
<h3 id="heading-how-to-use-benchmarking-tools">How to Use Benchmarking Tools</h3>
<p>Benchmarking Java applications provides valuable performance data and helps you identify areas for improvement. Effective benchmarking tools allow you to compare different approaches, algorithms, or libraries, enabling you to make informed decisions to enhance performance.</p>
<p><strong>Benchmarking Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Example code demonstrating benchmarking</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SortingBenchmark</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Generate an array of numbers</span>
        <span class="hljs-keyword">int</span>[] numbers = generateRandomNumbers(<span class="hljs-number">1000000</span>);

        <span class="hljs-comment">// Measure the execution time of different sorting algorithms</span>
        <span class="hljs-keyword">long</span> startTime = System.nanoTime();
        BubbleSort.sort(numbers);
        <span class="hljs-keyword">long</span> endTime = System.nanoTime();
        <span class="hljs-keyword">long</span> bubbleSortTime = endTime - startTime;

        startTime = System.nanoTime();
        QuickSort.sort(numbers);
        endTime = System.nanoTime();
        <span class="hljs-keyword">long</span> quickSortTime = endTime - startTime;

        <span class="hljs-comment">// Print the results</span>
        System.out.println(<span class="hljs-string">"Bubble Sort Time: "</span> + bubbleSortTime + <span class="hljs-string">" nanoseconds"</span>);
        System.out.println(<span class="hljs-string">"Quick Sort Time: "</span> + quickSortTime + <span class="hljs-string">" nanoseconds"</span>);
    }

    <span class="hljs-comment">// Helper method to generate random numbers</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span>[] generateRandomNumbers(<span class="hljs-keyword">int</span> size) {
        <span class="hljs-comment">// ...</span>
        <span class="hljs-keyword">return</span> numbers;
    }
}
</code></pre>
<h3 id="heading-how-to-use-monitoring-tools">How to Use Monitoring Tools</h3>
<p>Real-time monitoring of Java applications provides crucial insights into system behavior and performance metrics. Top Java monitoring tools enable you to track key performance indicators, detect anomalies, and troubleshoot issues promptly, ensuring optimal performance.</p>
<p>Remember, while utilizing these tools is essential, it's equally important to focus on writing clean and maintainable code, avoiding common pitfalls, and implementing efficient memory management strategies.</p>
<h3 id="heading-best-practices-in-java-optimization">Best Practices in Java Optimization</h3>
<p>Writing clean and maintainable code is crucial for optimizing Java applications. Adhering to principles of modularity and encapsulation, breaking down code into reusable modules, and encapsulating data and functionality within classes are key practices. </p>
<p>You should also avoid excessive object creation, choose efficient data structures, and employ memory management strategies like lazy initialization and resource cleanup.</p>
<h4 id="heading-example-of-clean-and-maintainable-code">Example of clean and maintainable code:</h4>
<p>Here's an example code snippet illustrating the importance of clean and maintainable code:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Example code demonstrating clean and maintainable code</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OrderProcessor</span> </span>{
    <span class="hljs-keyword">private</span> OrderRepository orderRepository;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">OrderProcessor</span><span class="hljs-params">(OrderRepository orderRepository)</span> </span>{
        <span class="hljs-keyword">this</span>.orderRepository = orderRepository;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processOrders</span><span class="hljs-params">(List&lt;Order&gt; orders)</span> </span>{
        <span class="hljs-keyword">for</span> (Order order : orders) {
            <span class="hljs-keyword">if</span> (order.isValid()) {
                order.process();
                orderRepository.save(order);
            }
        }
    }
}
</code></pre>
<p>The provided Java code is a good example of clean code for several reasons:</p>
<ol>
<li><strong>Single Responsibility Principle</strong>: The <code>OrderProcessor</code> class has a single responsibility – to process orders. This makes the class easier to maintain and test.</li>
<li><strong>Use of meaningful names</strong>: The class name <code>OrderProcessor</code> and method name <code>processOrders</code> clearly indicate their purpose. The variable names such as <code>orderRepository</code> and <code>orders</code> are also self-explanatory.</li>
<li><strong>Dependency Injection</strong>: The <code>OrderRepository</code> is passed into the <code>OrderProcessor</code> via its constructor, which is a form of Dependency Injection. This makes the code more flexible and easier to test.</li>
<li><strong>Code readability</strong>: The code is well-structured and easy to read. The use of whitespace and indentation improves readability.</li>
<li><strong>Error handling</strong>: The code checks if an order is valid before processing it, which is a good practice for error handling.</li>
</ol>
<p>Overall, this code is clean because it is easy to understand, maintain, and extend.</p>
<h2 id="heading-chapter-6-concurrent-data-structures-and-algorithms-for-high-performance-applications">Chapter 6: Concurrent Data Structures and Algorithms for High-Performance Applications</h2>
<p>In the fast-paced world of computing, where speed and efficiency are paramount, concurrent data structures and algorithms play a crucial role in achieving high performance. </p>
<p>Concurrency allows multiple tasks to execute simultaneously, maximizing resource utilization and enabling applications to handle complex workloads efficiently.</p>
<p>Understanding the fundamentals of concurrency in computing is essential for developers seeking to optimize their applications. By harnessing the power of parallelism, concurrent data structures and algorithms enable tasks to be executed concurrently, reducing overall execution time and improving responsiveness.</p>
<h3 id="heading-key-concurrent-data-structures">Key Concurrent Data Structures</h3>
<p><strong>Lock-based</strong> data structures provide a mechanism for ensuring mutual exclusion and data consistency in concurrent applications. They work by acquiring a lock or mutex before accessing shared data, ensuring that only one thread can access the data at a time. Common lock-based structures include locks, mutexes, and semaphores.</p>
<p><strong>Lock-free</strong> data structures, on the other hand, offer a way to achieve concurrency without the use of locks. They utilize atomic operations and memory fences to ensure data consistency and avoid the need for explicit locking. Examples of lock-free structures include lock-free queues and lock-free stacks.</p>
<p><strong>Wait-free</strong> data structures take concurrency a step further by guaranteeing that every thread makes progress even if other threads are stalled or delayed. They are designed to ensure that no thread is blocked indefinitely, making them suitable for real-time systems and high-performance applications.</p>
<p>We'll see some examples of these in a minute.</p>
<p>Remember, when utilizing lock-based data structures, it is crucial to handle potential issues such as deadlocks and contention. Always aim to strike a balance between concurrency and performance, ensuring efficient utilization of resources.</p>
<p>When working with lock-free and wait-free data structures, it is important to understand their limitations and use them judiciously. These structures can provide significant performance benefits in certain scenarios, but they may also introduce additional complexity and require careful synchronization.</p>
<p>By leveraging the appropriate concurrent data structures and algorithms in your Java applications, you can optimize performance, enhance responsiveness, and achieve efficient resource utilization.</p>
<h3 id="heading-essential-concurrent-algorithms">Essential Concurrent Algorithms</h3>
<p>In high-performance applications, concurrent data structures and algorithms are essential for achieving optimal speed and efficiency. They enable tasks to be executed simultaneously, maximizing resource utilization and improving responsiveness.</p>
<p>One important aspect of concurrency is task scheduling algorithms. These algorithms play a critical role in managing concurrent tasks. They determine the order in which tasks are executed and ensure efficient utilization of resources. </p>
<p>Here's an example of a round-robin scheduling algorithm implemented in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.Queue;
<span class="hljs-keyword">import</span> java.util.LinkedList;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RoundRobinScheduler</span> </span>{
    <span class="hljs-keyword">private</span> Queue&lt;Task&gt; taskQueue;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">RoundRobinScheduler</span><span class="hljs-params">()</span> </span>{
        taskQueue = <span class="hljs-keyword">new</span> LinkedList&lt;&gt;();
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">schedule</span><span class="hljs-params">(Task task)</span> </span>{
        taskQueue.offer(task);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">executeTasks</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">while</span> (!taskQueue.isEmpty()) {
            Task task = taskQueue.poll();
            task.execute();
            taskQueue.offer(task);
        }
    }
}
</code></pre>
<p>Synchronization algorithms are crucial for ensuring data consistency in concurrent applications. They prevent data races and conflicts by providing mechanisms for thread synchronization. </p>
<p>Here's an example of using locks for synchronization in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.concurrent.locks.Lock;
<span class="hljs-keyword">import</span> java.util.concurrent.locks.ReentrantLock;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SynchronizedData</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> data;
    <span class="hljs-keyword">private</span> Lock lock;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">SynchronizedData</span><span class="hljs-params">()</span> </span>{
        data = <span class="hljs-number">0</span>;
        lock = <span class="hljs-keyword">new</span> ReentrantLock();
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">updateData</span><span class="hljs-params">(<span class="hljs-keyword">int</span> value)</span> </span>{
        lock.lock();
        <span class="hljs-keyword">try</span> {
            data = value;
        } <span class="hljs-keyword">finally</span> {
            lock.unlock();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getData</span><span class="hljs-params">()</span> </span>{
        lock.lock();
        <span class="hljs-keyword">try</span> {
            <span class="hljs-keyword">return</span> data;
        } <span class="hljs-keyword">finally</span> {
            lock.unlock();
        }
    }
}
</code></pre>
<p>Deadlock detection and resolution are vital for handling potential deadlocks in concurrent applications, as we discussed above. If you remember, deadlocks occur when two or more threads are blocked indefinitely, waiting for each other to release resources. </p>
<p>Here's an example of deadlock prevention using resource ordering in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DeadlockPrevention</span> </span>{
    <span class="hljs-keyword">private</span> Object resource1 = <span class="hljs-keyword">new</span> Object();
    <span class="hljs-keyword">private</span> Object resource2 = <span class="hljs-keyword">new</span> Object();

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">executeThread1</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource1) {
            <span class="hljs-comment">// Critical section 1</span>
            <span class="hljs-keyword">synchronized</span> (resource2) {
                <span class="hljs-comment">// Critical section 2</span>
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">executeThread2</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">synchronized</span> (resource2) {
            <span class="hljs-comment">// Critical section 1</span>
            <span class="hljs-keyword">synchronized</span> (resource1) {
                <span class="hljs-comment">// Critical section 2</span>
            }
        }
    }
}
</code></pre>
<p>By leveraging the appropriate concurrent data structures, algorithms, and synchronization techniques, you can optimize the performance of your Java applications. Remember to consider the limitations and complexities of concurrent programming and aim for simplicity and efficiency in your implementation.</p>
<h3 id="heading-examples-of-lock-based-lock-free-and-wait-free-data-structures">Examples of Lock-based, Lock-free, and Wait-free Data Structures</h3>
<p>Concurrent data structures and algorithms play a crucial role in achieving high performance in the fast-paced world of computing. By allowing multiple tasks to execute simultaneously, concurrency maximizes resource utilization and enables efficient handling of complex workloads.</p>
<h4 id="heading-lock-based-data-structure">Lock-based data structure</h4>
<p>Lock-based data structures, such as locks, mutexes, and semaphores, ensure mutual exclusion and data consistency by acquiring locks before accessing shared data. </p>
<p>For example, in Java, you can use a lock-based data structure like the following code snippet:</p>
<pre><code class="lang-java"><span class="hljs-comment">// Importing the necessary classes from the java.util.concurrent.locks package</span>
<span class="hljs-keyword">import</span> java.util.concurrent.locks.Lock;
<span class="hljs-keyword">import</span> java.util.concurrent.locks.ReentrantLock;

<span class="hljs-comment">// Defining a public class named Counter</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Counter</span> </span>{
    <span class="hljs-comment">// Declaring a private integer variable 'count'</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> count;
    <span class="hljs-comment">// Declaring a private Lock object 'lock'</span>
    <span class="hljs-keyword">private</span> Lock lock;

    <span class="hljs-comment">// Defining the constructor for the Counter class</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Counter</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Initializing 'count' to 0</span>
        count = <span class="hljs-number">0</span>;
        <span class="hljs-comment">// Initializing 'lock' as a new ReentrantLock object</span>
        lock = <span class="hljs-keyword">new</span> ReentrantLock();
    }

    <span class="hljs-comment">// Defining a public method 'increment' to increment the count</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">increment</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Locking to ensure thread safety</span>
        lock.lock();
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Incrementing the count</span>
            count++;
        } <span class="hljs-keyword">finally</span> {
            <span class="hljs-comment">// Unlocking after incrementing</span>
            lock.unlock();
        }
    }

    <span class="hljs-comment">// Defining a public method 'getCount' to return the current count</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getCount</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Returning the current count</span>
        <span class="hljs-keyword">return</span> count;
    }
}
</code></pre>
<p>The <code>lock</code> variable is an instance of the <code>ReentrantLock</code> class from the <code>java.util.concurrent.locks</code> package, which is a reentrant mutual exclusion <code>Lock</code> with the same basic behavior and semantics as the implicit monitor lock accessed using <code>synchronized</code> methods and statements, but with extended capabilities. </p>
<p>The <code>ReentrantLock</code> allows more flexible structuring, may have completely different properties, and may support multiple associated <code>Condition</code> objects. </p>
<p>The use of <code>ReentrantLock</code> helps to ensure that the <code>increment()</code> operation is thread-safe. This is crucial in a multi-threaded environment to prevent race conditions.</p>
<h4 id="heading-lock-free-data-structure">Lock-free data structure</h4>
<p>On the other hand, lock-free data structures, such as lock-free queues and lock-free stacks, achieve concurrency without the use of locks. They employ atomic operations and memory fences to ensure data consistency. </p>
<pre><code><span class="hljs-keyword">import</span> java.util.concurrent.atomic.AtomicReference;

<span class="hljs-comment">// Node class to hold the data and the reference to the next node</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Node</span>&lt;<span class="hljs-title">E</span>&gt; </span>{
    final E item;
    Node&lt;E&gt; next;

    public Node(E item) {
        <span class="hljs-built_in">this</span>.item = item;
    }
}

<span class="hljs-comment">// Lock-free Stack class</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LockFreeStack</span>&lt;<span class="hljs-title">E</span>&gt; </span>{
    <span class="hljs-comment">// AtomicReference to the top of the stack</span>
    private AtomicReference&lt;Node&lt;E&gt;&gt; top = <span class="hljs-keyword">new</span> AtomicReference&lt;&gt;();

    <span class="hljs-comment">// Method to push an item onto the stack</span>
    public <span class="hljs-keyword">void</span> push(E item) {
        Node&lt;E&gt; newHead = <span class="hljs-keyword">new</span> Node&lt;&gt;(item);
        Node&lt;E&gt; oldHead;
        <span class="hljs-keyword">do</span> {
            oldHead = top.get();
            newHead.next = oldHead;
        } <span class="hljs-keyword">while</span> (!top.compareAndSet(oldHead, newHead));
    }

    <span class="hljs-comment">// Method to pop an item from the stack</span>
    public E pop() {
        Node&lt;E&gt; oldHead;
        Node&lt;E&gt; newHead;
        <span class="hljs-keyword">do</span> {
            oldHead = top.get();
            <span class="hljs-keyword">if</span> (oldHead == <span class="hljs-literal">null</span>) <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
            newHead = oldHead.next;
        } <span class="hljs-keyword">while</span> (!top.compareAndSet(oldHead, newHead));
        <span class="hljs-keyword">return</span> oldHead.item;
    }
}
</code></pre><p>In this code, <code>AtomicReference</code> is used to ensure that the operations on the <code>top</code> of the stack are atomic. The <code>push</code> and <code>pop</code> methods use a loop with <code>compareAndSet</code> to ensure that the operation is retried if the <code>top</code> was modified by another thread in the meantime. </p>
<p>This is a simple example of a lock-free data structure that achieves concurrency without the use of locks. But it’s important to note that while lock-free data structures can improve performance in multi-threaded environments, they can be more complex to implement correctly and may not always provide the best solution depending on the specific requirements of your application. It’s always important to understand their limitations and use them judiciously.</p>
<h4 id="heading-wait-free-data-structure">Wait-free data structure</h4>
<p>Wait-free data structures guarantee that every thread makes progress, even if other threads are stalled or delayed. They are suitable for real-time systems and high-performance applications.</p>
<pre><code><span class="hljs-keyword">import</span> java.util.concurrent.atomic.AtomicReference;

<span class="hljs-comment">// Node class to hold the data and the reference to the next node</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Node</span>&lt;<span class="hljs-title">E</span>&gt; </span>{
    final E item;
    AtomicReference&lt;Node&lt;E&gt;&gt; next;

    public Node(E item, Node&lt;E&gt; next) {
        <span class="hljs-built_in">this</span>.item = item;
        <span class="hljs-built_in">this</span>.next = <span class="hljs-keyword">new</span> AtomicReference&lt;&gt;(next);
    }
}

<span class="hljs-comment">// Wait-free Queue class</span>
public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">WaitFreeQueue</span>&lt;<span class="hljs-title">E</span>&gt; </span>{
    private AtomicReference&lt;Node&lt;E&gt;&gt; head, tail;

    public WaitFreeQueue() {
        Node&lt;E&gt; dummy = <span class="hljs-keyword">new</span> Node&lt;&gt;(<span class="hljs-literal">null</span>, <span class="hljs-literal">null</span>);
        head = <span class="hljs-keyword">new</span> AtomicReference&lt;&gt;(dummy);
        tail = <span class="hljs-keyword">new</span> AtomicReference&lt;&gt;(dummy);
    }

    <span class="hljs-comment">// Method to add an item to the queue</span>
    public <span class="hljs-keyword">void</span> enqueue(E item) {
        Node&lt;E&gt; newNode = <span class="hljs-keyword">new</span> Node&lt;&gt;(item, <span class="hljs-literal">null</span>);
        <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
            Node&lt;E&gt; curTail = tail.get();
            Node&lt;E&gt; tailNext = curTail.next.get();
            <span class="hljs-keyword">if</span> (curTail == tail.get()) {
                <span class="hljs-keyword">if</span> (tailNext != <span class="hljs-literal">null</span>) {
                    <span class="hljs-comment">// Queue in intermediate state, advance tail</span>
                    tail.compareAndSet(curTail, tailNext);
                } <span class="hljs-keyword">else</span> {
                    <span class="hljs-comment">// In quiescent state, try inserting new node</span>
                    <span class="hljs-keyword">if</span> (curTail.next.compareAndSet(<span class="hljs-literal">null</span>, newNode)) {
                        <span class="hljs-comment">// Insertion succeeded, try advancing tail</span>
                        tail.compareAndSet(curTail, newNode);
                        <span class="hljs-keyword">return</span>;
                    }
                }
            }
        }
    }

    <span class="hljs-comment">// Method to remove an item from the queue</span>
    public E dequeue() {
        <span class="hljs-keyword">while</span> (<span class="hljs-literal">true</span>) {
            Node&lt;E&gt; curHead = head.get();
            Node&lt;E&gt; curTail = tail.get();
            Node&lt;E&gt; headNext = curHead.next.get();
            <span class="hljs-keyword">if</span> (curHead == head.get()) {
                <span class="hljs-keyword">if</span> (curHead == curTail) {
                    <span class="hljs-keyword">if</span> (headNext == <span class="hljs-literal">null</span>) {
                        <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>; <span class="hljs-comment">// Queue is empty</span>
                    }
                    <span class="hljs-comment">// Queue in intermediate state, advance tail</span>
                    tail.compareAndSet(curTail, headNext);
                } <span class="hljs-keyword">else</span> {
                    E item = headNext.item;
                    <span class="hljs-keyword">if</span> (head.compareAndSet(curHead, headNext)) {
                        <span class="hljs-keyword">return</span> item;
                    }
                }
            }
        }
    }
}
</code></pre><p>In this code, <code>AtomicReference</code> is used to ensure that the operations on the <code>head</code> and <code>tail</code> of the queue are atomic. </p>
<p>The <code>enqueue</code> and <code>dequeue</code> methods use a loop with <code>compareAndSet</code> to ensure that the operation is retried if the <code>head</code> or <code>tail</code> was modified by another thread in the meantime. </p>
<p>This is a simple example of a wait-free data structure that guarantees that every thread makes progress, even if other threads are stalled or delayed. But it’s important to note that while wait-free data structures can improve performance in multi-threaded environments, they can be more complex to implement correctly and may not always provide the best solution depending on the specific requirements of your application. It’s always important to understand their limitations and use them judiciously.</p>
<p>In real-world applications, concurrent structures find applications in scenarios where high-performance and efficient resource utilization are critical. Learning from successful implementations can provide valuable insights and practical advice for optimizing your own applications.</p>
<h2 id="heading-chapter-7-fundamentals-of-java-security">Chapter 7: Fundamentals of Java Security</h2>
<p>Understanding the importance of Java security is crucial in today's digital landscape. Over the years, Java security has evolved to address emerging threats and provide robust protection for applications and data. Let's delve into these key concepts and explore their practical implications.</p>
<p>When it comes to Java security, you'll want to prioritize the safety of your applications and the sensitive information they handle. By implementing strong security measures, you can safeguard against unauthorized access, data breaches, and malicious attacks.</p>
<p>To illustrate the significance of Java security, consider the following example code snippet:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.security.MessageDigest;
<span class="hljs-keyword">import</span> java.security.NoSuchAlgorithmException;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.Scanner;
<span class="hljs-keyword">import</span> java.util.logging.Logger;
<span class="hljs-keyword">import</span> java.util.logging.Level;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureApplication</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Logger LOGGER = Logger.getLogger(SecureApplication.class.getName());
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> HashMap&lt;String, String&gt; userDatabase = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();

    <span class="hljs-keyword">static</span> {
        <span class="hljs-comment">// Ideally, passwords should be hashed using a secure algorithm with a salt</span>
        userDatabase.put(<span class="hljs-string">"user1"</span>, hashPassword(<span class="hljs-string">"password123"</span>));
        userDatabase.put(<span class="hljs-string">"admin"</span>, hashPassword(<span class="hljs-string">"adminSecure!"</span>));
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> (Scanner scanner = <span class="hljs-keyword">new</span> Scanner(System.in)) {
            System.out.print(<span class="hljs-string">"Enter username: "</span>);
            String username = scanner.nextLine();
            System.out.print(<span class="hljs-string">"Enter password: "</span>);
            String password = scanner.nextLine();

            <span class="hljs-keyword">if</span> (authenticate(username, password)) {
                LOGGER.info(<span class="hljs-string">"User authenticated successfully."</span>);
                <span class="hljs-keyword">if</span> (isAuthorized(username)) {
                    performSecureOperations();
                } <span class="hljs-keyword">else</span> {
                    LOGGER.warning(<span class="hljs-string">"Access Denied: User does not have the necessary permissions."</span>);
                }
            } <span class="hljs-keyword">else</span> {
                LOGGER.severe(<span class="hljs-string">"Authentication Failed: Invalid username or password."</span>);
            }
        } <span class="hljs-keyword">catch</span> (Exception e) {
            LOGGER.log(Level.SEVERE, <span class="hljs-string">"An error occurred"</span>, e);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">authenticate</span><span class="hljs-params">(String username, String password)</span> </span>{
        <span class="hljs-keyword">return</span> userDatabase.containsKey(username) &amp;&amp; userDatabase.get(username).equals(hashPassword(password));
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isAuthorized</span><span class="hljs-params">(String username)</span> </span>{
        <span class="hljs-comment">// Implement authorization logic</span>
        <span class="hljs-comment">// For example, only 'admin' has access to perform secure operations</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"admin"</span>.equals(username);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">performSecureOperations</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Secure operations</span>
        System.out.println(<span class="hljs-string">"Performing secure operations..."</span>);
        <span class="hljs-comment">// Operations go here</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">hashPassword</span><span class="hljs-params">(String password)</span> </span>{
        <span class="hljs-keyword">try</span> {
            MessageDigest md = MessageDigest.getInstance(<span class="hljs-string">"SHA-256"</span>);
            <span class="hljs-keyword">byte</span>[] hashedPassword = md.digest(password.getBytes());
            <span class="hljs-keyword">return</span> bytesToHex(hashedPassword);
        } <span class="hljs-keyword">catch</span> (NoSuchAlgorithmException e) {
            LOGGER.log(Level.SEVERE, <span class="hljs-string">"Hashing algorithm not found"</span>, e);
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">bytesToHex</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] bytes)</span> </span>{
        StringBuilder hexString = <span class="hljs-keyword">new</span> StringBuilder();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">byte</span> b : bytes) {
            String hex = Integer.toHexString(<span class="hljs-number">0xff</span> &amp; b);
            <span class="hljs-keyword">if</span> (hex.length() == <span class="hljs-number">1</span>) hexString.append(<span class="hljs-string">'0'</span>);
            hexString.append(hex);
        }
        <span class="hljs-keyword">return</span> hexString.toString();
    }
}
</code></pre>
<p>This Java code sample illustrates the significance of Java security in several ways:</p>
<ol>
<li><strong>Hashing Passwords</strong>: The <code>hashPassword</code> method uses the <code>MessageDigest</code> class from the <code>java.security</code> package to hash passwords using the SHA-256 algorithm. Hashing passwords is a critical security practice because it means that even if an attacker gains access to the password hash, they cannot easily determine the original password.</li>
<li><strong>User Authentication</strong>: The <code>authenticate</code> method checks if the entered username exists in the <code>userDatabase</code> and if the hashed version of the entered password matches the stored hashed password. This is a basic form of user authentication, which is crucial for protecting user accounts and data.</li>
<li><strong>User Authorization</strong>: The <code>isAuthorized</code> method checks if the authenticated user has the necessary permissions to perform secure operations. This is an example of user authorization, which is important for ensuring that users can only perform actions they are allowed to.</li>
<li><strong>Exception Handling</strong>: The code includes exception handling to deal with potential errors, such as the <code>NoSuchAlgorithmException</code> that might be thrown when getting an instance of <code>MessageDigest</code>. Proper exception handling is important for both security and reliability.</li>
<li><strong>Secure Operations</strong>: The <code>performSecureOperations</code> method is a placeholder for operations that should only be performed by authorized users. Ensuring that only authorized users can perform sensitive operations is a key aspect of application security.</li>
<li><strong>Logging</strong>: The code uses a <code>Logger</code> to record information about authentication and authorization processes. Logging is important for monitoring and troubleshooting security-related events.</li>
</ol>
<p>These security features are all critical for building secure Java applications. But it’s important to note that this is a simplified example and real-world applications would require additional security measures.</p>
<p>Through regular updates and patches, Java vulnerabilities are addressed, and new features are introduced to mitigate emerging risks. Staying up to date with the latest security practices and incorporating them into your development process is essential for maintaining a secure Java environment.</p>
<p>Let's dive into security principles and best practices in more detail.</p>
<h3 id="heading-what-is-java-security">What Is Java Security?</h3>
<p>Java security refers to the measures and mechanisms in place to safeguard applications and data from unauthorized access, breaches, and malicious attacks. It encompasses a range of practices, including authentication, authorization, encryption, secure coding, and more. </p>
<p>By implementing robust security measures, you can create a secure environment that inspires user confidence and protects valuable information.</p>
<h3 id="heading-core-principles-of-java-security">Core Principles of Java Security</h3>
<p>Java security is built upon several core principles that guide the development and implementation of secure applications:</p>
<h4 id="heading-authentication">Authentication</h4>
<p>Authentication is a fundamental aspect of cybersecurity. It serves as the first line of defense in securing sensitive resources and functionalities by ensuring that only verified users gain access. In the context of Java, there are several ways to implement authentication, each with its own significance.</p>
<p>Validating usernames and passwords is the most basic form of authentication. It involves checking the entered credentials against a database of registered users. </p>
<p>While simple, this method is susceptible to various attacks such as brute force or dictionary attacks. So it’s crucial to store passwords securely, often as hashed values rather than plain text. Java provides several libraries for secure password hashing, such as Bcrypt.</p>
<p>Example Code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PasswordHashingExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        BCryptPasswordEncoder passwordEncoder = <span class="hljs-keyword">new</span> BCryptPasswordEncoder();
        String hashedPassword = passwordEncoder.encode(<span class="hljs-string">"myPassword"</span>);

        System.out.println(hashedPassword);
    }
}
</code></pre>
<p>Multi-factor authentication (MFA) adds an extra layer of security. It requires users to provide two or more verification factors to gain access. These factors could be something the user knows (like a password), something the user has (like a hardware token or phone), or something the user is (like a fingerprint or other biometric trait). </p>
<p>MFA significantly improves security because even if an attacker obtains one factor (like the user’s password), they still need the other factor(s) to gain access.</p>
<p>External authentication systems, such as OAuth2 or OpenID Connect, allow users to authenticate using an external trusted provider (like Google or Facebook). These systems can provide a secure and user-friendly way to handle authentication, as they offload the responsibility of secure credential storage to the external provider. Java has several libraries, like Spring Security, that provide out-of-the-box support for these systems.</p>
<h4 id="heading-authorization">Authorization</h4>
<p>Access control is a critical aspect of cybersecurity, particularly in Java applications. It involves defining and enforcing policies that determine which users have permissions to access specific resources or perform certain operations within the application.</p>
<p>In a typical Java application, access control can be implemented at various levels. For instance, at the method level, developers can use Java’s built-in access modifiers (public, private, protected, and package-private) to control which other classes can call a particular method. However, for more granular and dynamic access control, developers often turn to frameworks like Spring Security.</p>
<p>Spring Security provides a comprehensive security solution for Java applications. It includes support for both authentication (verifying who a user is) and authorization (controlling what a user can do).</p>
<p>For example, consider a web application where only authenticated users should be able to access certain pages. With Spring Security, developers can annotate controller methods with <code>@PreAuthorize</code> to specify access control rules. Here’s an example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.springframework.security.access.prepost.PreAuthorize;
<span class="hljs-keyword">import</span> org.springframework.stereotype.Controller;
<span class="hljs-keyword">import</span> org.springframework.web.bind.annotation.GetMapping;

<span class="hljs-meta">@Controller</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyController</span> </span>{

    <span class="hljs-meta">@PreAuthorize("hasRole('ADMIN')")</span>
    <span class="hljs-meta">@GetMapping("/admin")</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">adminPage</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"admin"</span>;
    }
}
</code></pre>
<p>In this code, the <code>@PreAuthorize</code> annotation ensures that only users with the ‘ADMIN’ role can access the ‘admin’ page. If a user without the ‘ADMIN’ role tries to access this page, Spring Security will block the request.</p>
<p>This is just one example of how access control can be implemented in Java. The key is to carefully define access control policies that align with the application’s requirements and to enforce these policies consistently throughout the application. This helps to ensure that sensitive resources and operations are protected from unauthorized access, thereby enhancing the overall security of the application. </p>
<h4 id="heading-secure-coding">Secure Coding</h4>
<p>Secure coding practices are essential in Java cybersecurity. They help eliminate vulnerabilities and prevent common exploits, thereby enhancing the overall security of Java applications.</p>
<p>Input validation is one such practice. It involves checking the data provided by users to ensure it meets specific criteria before processing it. </p>
<p>This is crucial because unvalidated or improperly validated inputs can lead to various types of attacks, such as SQL injection, cross-site scripting (XSS), and command injection. </p>
<p>In Java, you can perform input validation using various methods, such as regular expressions, built-in functions, or third-party libraries.</p>
<p>Here’s an example of basic input validation in Java:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isValidUsername</span><span class="hljs-params">(String username)</span> </span>{
    String regex = <span class="hljs-string">"^[a-zA-Z0-9_]+$"</span>;
    <span class="hljs-keyword">return</span> username.matches(regex);
}
</code></pre>
<p>In this code, the <code>isValidUsername</code> method checks if the provided username only contains alphanumeric characters and underscores, which is often a requirement for usernames.</p>
<p>Output encoding is another important secure coding practice. It involves encoding the data before sending it to the client to prevent attacks like XSS, where an attacker injects malicious scripts into content that’s displayed to other users. </p>
<p>Java provides several ways to perform output encoding, such as using the <code>escapeHtml4</code> method from the Apache Commons Text library to encode HTML content.</p>
<p>Parameterized queries, also known as prepared statements, are used to prevent SQL injection attacks. </p>
<p>SQL injection is a technique where an attacker inserts malicious SQL code into a query, which can then be executed by the database. By using parameterized queries, you ensure that user input is always treated as literal data, not part of the SQL command.</p>
<p>Here’s an example of a parameterized query in Java using JDBC:</p>
<pre><code class="lang-java">String query = <span class="hljs-string">"SELECT * FROM users WHERE username = ?"</span>;
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(<span class="hljs-number">1</span>, username);
ResultSet rs = pstmt.executeQuery();
</code></pre>
<p>In this code, the <code>?</code> is a placeholder that gets replaced with the <code>username</code> variable. Because the <code>username</code> is automatically escaped by the <code>PreparedStatement</code>, it’s not possible for an attacker to inject malicious SQL code via the <code>username</code>.</p>
<p>Following secure coding practices like input validation, output encoding, and using parameterized queries is crucial for preventing common exploits and enhancing the security of Java applications. </p>
<h4 id="heading-encryption">Encryption</h4>
<p>Protecting sensitive data, both at rest and in transit, is a cornerstone of cybersecurity. Encryption plays a vital role in this protection. It involves converting plaintext data into ciphertext using an encryption algorithm, rendering it unreadable to anyone without the decryption key.</p>
<p>In Java, the Java Cryptography Extension (JCE) provides functionalities for encryption and decryption. It supports various encryption algorithms, including AES (Advanced Encryption Standard), which is widely recognized for its strength and efficiency.</p>
<p>Here’s an example of how you might use AES encryption to protect data at rest in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> javax.crypto.Cipher;
<span class="hljs-keyword">import</span> javax.crypto.KeyGenerator;
<span class="hljs-keyword">import</span> javax.crypto.SecretKey;
<span class="hljs-keyword">import</span> java.util.Base64;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AESEncryptionExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        <span class="hljs-comment">// Generate a new AES key</span>
        KeyGenerator keyGen = KeyGenerator.getInstance(<span class="hljs-string">"AES"</span>);
        keyGen.init(<span class="hljs-number">256</span>);
        SecretKey secretKey = keyGen.generateKey();

        <span class="hljs-comment">// Create a cipher instance and initialize it for encryption</span>
        Cipher cipher = Cipher.getInstance(<span class="hljs-string">"AES"</span>);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);

        <span class="hljs-comment">// Encrypt the data</span>
        String plaintext = <span class="hljs-string">"Sensitive data"</span>;
        <span class="hljs-keyword">byte</span>[] ciphertext = cipher.doFinal(plaintext.getBytes());

        <span class="hljs-comment">// Print the encrypted data</span>
        System.out.println(Base64.getEncoder().encodeToString(ciphertext));
    }
}
</code></pre>
<p>In this code, we first generate a new AES key. We then create a <code>Cipher</code> instance and initialize it for encryption using the generated key. Finally, we encrypt the plaintext data and print the resulting ciphertext.</p>
<p>When it comes to protecting data in transit, secure communication protocols like HTTPS (HTTP over SSL/TLS) are commonly used. These protocols use encryption to protect data as it travels over the network. In Java, you can use the <code>HttpsURLConnection</code> class or libraries like Apache HttpClient to send and receive data over HTTPS.</p>
<p>Managing encryption keys is another critical aspect of data protection. Keys need to be securely generated, stored, and managed. They should be rotated regularly and revoked if compromised. In Java, you can use the Java KeyStore (JKS) to securely store cryptographic keys.</p>
<p>Encryption is a powerful tool for protecting sensitive data in Java applications. By using strong encryption algorithms and properly managing encryption keys, you can significantly enhance the security of your data, both at rest and in transit.</p>
<h4 id="heading-logging-and-monitoring">Logging and Monitoring</h4>
<p>Implementing comprehensive logging and monitoring systems is a crucial aspect of cybersecurity in Java applications. These systems serve as the eyes and ears of your application, providing visibility into its operations and helping to detect and respond to security incidents effectively.</p>
<p>Logging involves recording events that occur in your application. These events can include user actions, system events, or errors. Logs can provide valuable information for troubleshooting issues, understanding user behavior, and detecting security incidents. </p>
<p>In Java, there are several libraries available for logging, such as Log4j, SLF4J, and java.util.logging.</p>
<p>Here’s an example of how you might use Log4j in a Java application:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> org.apache.logging.log4j.LogManager;
<span class="hljs-keyword">import</span> org.apache.logging.log4j.Logger;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LoggingExample</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Logger logger = LogManager.getLogger(LoggingExample.class);

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        logger.info(<span class="hljs-string">"This is an info message"</span>);
        logger.warn(<span class="hljs-string">"This is a warning message"</span>);
        logger.error(<span class="hljs-string">"This is an error message"</span>);
    }
}
</code></pre>
<p>In this code, we first create a <code>Logger</code> instance. We then use the <code>info</code>, <code>warn</code>, and <code>error</code> methods to log messages at different levels. These messages will be recorded in the application’s log file, where they can be reviewed later.</p>
<p>Monitoring, on the other hand, involves continuously observing your application to track its performance, identify issues, and detect potential security breaches. </p>
<p>Monitoring can help you identify suspicious activities, such as repeated failed login attempts, unexpected system behavior, or significant changes in traffic patterns, which could indicate a security incident.</p>
<p>Java provides several tools and libraries for monitoring, such as JMX (Java Management Extensions) for monitoring and managing Java applications, and third-party solutions like New Relic or Dynatrace for application performance monitoring.</p>
<p>By adhering to these core principles and incorporating them into the development process, developers can build robust and secure Java applications.</p>
<p>Remember, while these principles provide a solid foundation for Java security, it's essential to stay updated with the latest security practices, frameworks, and libraries. Regularly reviewing and enhancing security measures is crucial to adapt to emerging threats and ensure the ongoing protection of your Java applications.</p>
<p>By focusing on these fundamental aspects of Java security, you can create a secure and reliable environment for your applications and instill confidence in your users.</p>
<p>Here is a final code incorporating all the discussed aspects of Java security:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.security.MessageDigest;
<span class="hljs-keyword">import</span> java.security.NoSuchAlgorithmException;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.Scanner;
<span class="hljs-keyword">import</span> java.util.logging.Logger;
<span class="hljs-keyword">import</span> java.util.logging.Level;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureApplication</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> Logger LOGGER = Logger.getLogger(SecureApplication.class.getName());
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> HashMap&lt;String, String&gt; userDatabase = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();

    <span class="hljs-keyword">static</span> {
        <span class="hljs-comment">// Ideally, passwords should be hashed using a secure algorithm with a salt</span>
        userDatabase.put(<span class="hljs-string">"user1"</span>, hashPassword(<span class="hljs-string">"password123"</span>));
        userDatabase.put(<span class="hljs-string">"admin"</span>, hashPassword(<span class="hljs-string">"adminSecure!"</span>));
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> (Scanner scanner = <span class="hljs-keyword">new</span> Scanner(System.in)) {
            System.out.print(<span class="hljs-string">"Enter username: "</span>);
            String username = scanner.nextLine();
            System.out.print(<span class="hljs-string">"Enter password: "</span>);
            String password = scanner.nextLine();

            <span class="hljs-keyword">if</span> (authenticate(username, password)) {
                LOGGER.info(<span class="hljs-string">"User authenticated successfully."</span>);
                <span class="hljs-keyword">if</span> (isAuthorized(username)) {
                    performSecureOperations();
                } <span class="hljs-keyword">else</span> {
                    LOGGER.warning(<span class="hljs-string">"Access Denied: User does not have the necessary permissions."</span>);
                }
            } <span class="hljs-keyword">else</span> {
                LOGGER.severe(<span class="hljs-string">"Authentication Failed: Invalid username or password."</span>);
            }
        } <span class="hljs-keyword">catch</span> (Exception e) {
            LOGGER.log(Level.SEVERE, <span class="hljs-string">"An error occurred"</span>, e);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">authenticate</span><span class="hljs-params">(String username, String password)</span> </span>{
        <span class="hljs-keyword">return</span> userDatabase.containsKey(username) &amp;&amp; userDatabase.get(username).equals(hashPassword(password));
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">isAuthorized</span><span class="hljs-params">(String username)</span> </span>{
        <span class="hljs-comment">// Implement authorization logic</span>
        <span class="hljs-comment">// For example, only 'admin' has access to perform secure operations</span>
        <span class="hljs-keyword">return</span> <span class="hljs-string">"admin"</span>.equals(username);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">performSecureOperations</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Secure operations</span>
        System.out.println(<span class="hljs-string">"Performing secure operations..."</span>);
        <span class="hljs-comment">// Operations go here</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">hashPassword</span><span class="hljs-params">(String password)</span> </span>{
        <span class="hljs-keyword">try</span> {
            MessageDigest md = MessageDigest.getInstance(<span class="hljs-string">"SHA-256"</span>);
            <span class="hljs-keyword">byte</span>[] hashedPassword = md.digest(password.getBytes());
            <span class="hljs-keyword">return</span> bytesToHex(hashedPassword);
        } <span class="hljs-keyword">catch</span> (NoSuchAlgorithmException e) {
            LOGGER.log(Level.SEVERE, <span class="hljs-string">"Hashing algorithm not found"</span>, e);
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">bytesToHex</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] bytes)</span> </span>{
        StringBuilder hexString = <span class="hljs-keyword">new</span> StringBuilder();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">byte</span> b : bytes) {
            String hex = Integer.toHexString(<span class="hljs-number">0xff</span> &amp; b);
            <span class="hljs-keyword">if</span> (hex.length() == <span class="hljs-number">1</span>) hexString.append(<span class="hljs-string">'0'</span>);
            hexString.append(hex);
        }
        <span class="hljs-keyword">return</span> hexString.toString();
    }
}
</code></pre>
<p>This code integrates the discussed principles of Java security, such as authentication, authorization, secure coding, encryption, and logging. It provides a foundation for building secure Java applications and protecting sensitive information.</p>
<p>Remember to adapt and enhance the code based on specific application requirements and the latest security practices. Regularly review and update the code to address emerging threats and vulnerabilities, ensuring the ongoing security of your Java applications.</p>
<h3 id="heading-java-language-features-for-security">Java Language Features for Security</h3>
<p>When it comes to Java security, several key language features play a crucial role in ensuring the safety and protection of applications and data. Let's explore these features and understand their significance in securing Java code.</p>
<h4 id="heading-static-data-typing-enforcing-type-safety">Static Data Typing: Enforcing Type Safety</h4>
<p>One fundamental aspect of Java security is static data typing. By enforcing type safety, Java helps prevent common programming errors and vulnerabilities. </p>
<p>Static typing ensures that variables are declared with specific data types and that only compatible operations can be performed on them. This reduces the risk of type-related security issues, such as type confusion or type casting vulnerabilities.</p>
<p>For example, consider the following code snippet:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> userId = getUserInput();
String userName = getUserInput();

<span class="hljs-comment">// By enforcing static typing, the compiler detects type mismatches and prevents potential vulnerabilities</span>
</code></pre>
<p>In this example, the compiler will detect any attempts to assign an integer value to the <code>userName</code> variable, preventing potential security risks.</p>
<h4 id="heading-access-modifiers-controlling-visibility-and-accessibility">Access Modifiers: Controlling Visibility and Accessibility</h4>
<p>Access modifiers in Java, such as <code>public</code>, <code>private</code>, and <code>protected</code>, allow developers to control the visibility and accessibility of classes, methods, and variables. This plays a crucial role in ensuring the security of Java code by restricting access to sensitive information or functionalities.</p>
<p>For example, consider the following code snippet:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureApplication</span> </span>{
    <span class="hljs-keyword">private</span> String sensitiveData; <span class="hljs-comment">// Accessible only within the class</span>

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">processSensitiveData</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Accessing the sensitive data within the class</span>
    }
}

<span class="hljs-comment">// By using access modifiers appropriately, sensitive data and operations can be protected from unauthorized access</span>
</code></pre>
<p>In this example, the <code>sensitiveData</code> variable and the <code>processSensitiveData</code> method are declared as <code>private</code>, ensuring that they can be accessed only within the <code>SecureApplication</code> class.</p>
<h4 id="heading-automatic-memory-management-mitigating-memory-related-vulnerabilities">Automatic Memory Management: Mitigating Memory-Related Vulnerabilities</h4>
<p>Java's automatic memory management, enabled by the garbage collector, plays a significant role in enhancing security by mitigating memory-related vulnerabilities. </p>
<p>By automatically deallocating memory that is no longer in use, Java helps prevent issues such as memory leaks and buffer overflows that can lead to security vulnerabilities.</p>
<p>For example, consider the following code snippet:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">processUserInput</span><span class="hljs-params">()</span> </span>{
    String userInput = getUserInput();
    <span class="hljs-comment">// Process the user input</span>
    <span class="hljs-comment">// Java's garbage collector automatically frees the memory occupied by the userInput variable</span>
}
</code></pre>
<p>In this example, Java's garbage collector ensures that the memory occupied by the <code>userInput</code> variable is automatically reclaimed after it is no longer needed, reducing the risk of memory-related vulnerabilities.</p>
<h4 id="heading-bytecode-verification-ensuring-safe-code-execution">Bytecode Verification: Ensuring Safe Code Execution</h4>
<p>Java's bytecode verification process plays a critical role in ensuring the safe execution of code. </p>
<p>When Java code is compiled, it is transformed into bytecode, which is then executed by the Java Virtual Machine (JVM). Before executing the bytecode, the JVM performs bytecode verification to ensure that it adheres to specific safety requirements. </p>
<p>This process helps prevent common security risks, such as stack overflow or buffer overflow vulnerabilities.</p>
<p>For example, consider the following code snippet:</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">processInput</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] inputData)</span> </span>{
    <span class="hljs-comment">// Process the input data</span>
}

<span class="hljs-comment">// By performing bytecode verification, the JVM ensures that the processInput method operates safely without causing buffer overflow or other security vulnerabilities</span>
</code></pre>
<p>In this example, the JVM verifies the bytecode of the <code>processInput</code> method to ensure that it operates safely, preventing potential security vulnerabilities.</p>
<p>By leveraging these language features, you can enhance the security of your Java code. But it's important to remember that these features alone are not sufficient to guarantee complete security. It is crucial to follow secure coding practices, apply encryption where necessary, and implement other security measures as required by your specific application and environment.</p>
<h3 id="heading-security-architecture-in-java">Security Architecture in Java</h3>
<h4 id="heading-overview-of-java-security-architecture">Overview of Java Security Architecture</h4>
<p>Java security architecture is designed to provide a secure environment for Java applications. It includes various components such as the Java Development Kit (JDK), Java Runtime Environment (JRE), and Java Virtual Machine (JVM). </p>
<p>The architecture ensures the enforcement of security policies, handling of permissions, and management of cryptographic services.</p>
<h4 id="heading-role-of-provider-implementations-in-java-security">Role of Provider Implementations in Java Security</h4>
<p>In Java, a provider refers to a package or a set of packages that supply a concrete implementation of a subset of the cryptography aspects of the Java Cryptography Architecture (JCA) and the Java Cryptography Extension (JCE). They supply the actual program code that implements standard algorithms such as RSA, DSA, and AES.</p>
<p>Provider implementations are indeed crucial in Java security. They provide the necessary cryptographic algorithms and services that are used for various purposes such as generating key pairs, creating secure random numbers, and creating message digests.</p>
<p>Java includes several built-in providers. For instance, SunJCE (Java Cryptography Extension) is a provider that offers a wide range of cryptographic functionalities including support for encryption, key generation and key agreement, and Message Authentication Code (MAC) algorithms.</p>
<p>SunPKCS11 is another provider that offers a wide range of cryptographic functionalities. It provides a bridge from the JCA to native PKCS11 cryptographic tokens. PKCS11 is a standard that defines a platform-independent API to cryptographic tokens, such as hardware security modules (HSM) and smart cards, and names the API itself “Cryptoki”.</p>
<p>While the built-in providers offer a wide range of cryptographic functionalities, Java also allows for custom providers. This means you can implement your own provider to extend the security capabilities of your Java applications. </p>
<p>This is particularly useful when you need to use cryptographic services that are not offered by the built-in providers or when you want to use a device-specific implementation.</p>
<p>Implementing a custom provider involves extending the <code>java.security.Provider</code> class and implementing the required cryptographic services. Once implemented, the provider can be dynamically registered at runtime by calling the <code>Security.addProvider()</code> method.</p>
<h4 id="heading-understanding-cryptographic-algorithms-in-java">Understanding Cryptographic Algorithms in Java</h4>
<p>Java supports a comprehensive set of cryptographic algorithms for various purposes, including encryption, digital signatures, and hash functions. These algorithms ensure the confidentiality, integrity, and authenticity of data. Some commonly used algorithms include AES, RSA, and SHA-256.</p>
<p>To illustrate the usage of cryptographic algorithms in Java, consider the following example code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> javax.crypto.Cipher;
<span class="hljs-keyword">import</span> java.security.Key;
<span class="hljs-keyword">import</span> java.security.KeyPair;
<span class="hljs-keyword">import</span> java.security.KeyPairGenerator;
<span class="hljs-keyword">import</span> java.security.NoSuchAlgorithmException;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CryptographyExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Generate a key pair for asymmetric encryption</span>
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(<span class="hljs-string">"RSA"</span>);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            Key publicKey = keyPair.getPublic();
            Key privateKey = keyPair.getPrivate();

            <span class="hljs-comment">// Encrypt data using the public key</span>
            Cipher cipher = Cipher.getInstance(<span class="hljs-string">"RSA"</span>);
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            <span class="hljs-keyword">byte</span>[] encryptedData = cipher.doFinal(<span class="hljs-string">"Hello, world!"</span>.getBytes());

            <span class="hljs-comment">// Decrypt the encrypted data using the private key</span>
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            <span class="hljs-keyword">byte</span>[] decryptedData = cipher.doFinal(encryptedData);

            System.out.println(<span class="hljs-string">"Decrypted data: "</span> + <span class="hljs-keyword">new</span> String(decryptedData));
        } <span class="hljs-keyword">catch</span> (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | IllegalBlockSizeException | BadPaddingException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<p>In this example, we generate a key pair using the RSA algorithm, encrypt the data using the public key, and then decrypt it using the private key.</p>
<p>By understanding Java security architecture, provider implementations, and cryptographic algorithms, you can effectively implement secure solutions in your Java applications. </p>
<h3 id="heading-cryptography-in-java">Cryptography in Java</h3>
<p>In Java Cryptographic Architecture (JCA), you have access to a wide range of cryptographic functionalities to enhance the security of your Java applications. Let's explore some key concepts and techniques that can be implemented in Java code.</p>
<h4 id="heading-introduction-to-java-cryptographic-architecture-jca">Introduction to Java Cryptographic Architecture (JCA)</h4>
<p>To ensure the confidentiality, integrity, and authenticity of data, JCA provides a framework for implementing cryptographic algorithms and services. It includes classes and interfaces that allow you to perform various cryptographic operations, such as encryption, decryption, digital signatures, and message digests.</p>
<h4 id="heading-how-to-implement-digital-signatures-and-message-digests">How to Implement Digital Signatures and Message Digests</h4>
<p>Digital signatures provide a way to verify the authenticity and integrity of data. By generating a digital signature, you can ensure that the data has not been tampered with during transmission or storage. </p>
<p>Message digests, on the other hand, create a fixed-size hash value representing the input data. This hash value can be used to verify the integrity of the data.</p>
<p>Here is an example of generating a digital signature and verifying it using Java code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.security.*;
<span class="hljs-keyword">import</span> java.util.Base64;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">DigitalSignatureExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Generate key pair</span>
            KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(<span class="hljs-string">"RSA"</span>);
            KeyPair keyPair = keyPairGenerator.generateKeyPair();
            PrivateKey privateKey = keyPair.getPrivate();
            PublicKey publicKey = keyPair.getPublic();

            <span class="hljs-comment">// Generate a digital signature</span>
            Signature signature = Signature.getInstance(<span class="hljs-string">"SHA256withRSA"</span>);
            signature.initSign(privateKey);
            <span class="hljs-keyword">byte</span>[] inputData = <span class="hljs-string">"Hello, world!"</span>.getBytes();
            signature.update(inputData);
            <span class="hljs-keyword">byte</span>[] digitalSignature = signature.sign();

            <span class="hljs-comment">// Verify the digital signature</span>
            signature.initVerify(publicKey);
            signature.update(inputData);
            <span class="hljs-keyword">boolean</span> verified = signature.verify(digitalSignature);

            System.out.println(<span class="hljs-string">"Digital Signature Verified: "</span> + verified);
        } <span class="hljs-keyword">catch</span> (NoSuchAlgorithmException | InvalidKeyException | SignatureException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<h4 id="heading-symmetric-vs-asymmetric-ciphers">Symmetric vs. Asymmetric Ciphers</h4>
<p>Symmetric ciphers use the same key for both encryption and decryption, while asymmetric ciphers use different keys for these operations. </p>
<p>Symmetric ciphers are generally faster but require a secure method of key exchange. Asymmetric ciphers provide a secure way to exchange keys but are slower than symmetric ciphers.</p>
<p>Here is an example of using symmetric and asymmetric ciphers in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> javax.crypto.*;
<span class="hljs-keyword">import</span> javax.crypto.spec.SecretKeySpec;
<span class="hljs-keyword">import</span> java.security.*;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CipherExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Symmetric encryption and decryption</span>
            SecretKey secretKey = generateSymmetricKey();
            String plainText = <span class="hljs-string">"Hello, world!"</span>;
            <span class="hljs-keyword">byte</span>[] encryptedData = encryptSymmetric(plainText, secretKey);
            String decryptedData = decryptSymmetric(encryptedData, secretKey);

            System.out.println(<span class="hljs-string">"Symmetric Encryption and Decryption:"</span>);
            System.out.println(<span class="hljs-string">"Plain Text: "</span> + plainText);
            System.out.println(<span class="hljs-string">"Encrypted Data: "</span> + <span class="hljs-keyword">new</span> String(encryptedData));
            System.out.println(<span class="hljs-string">"Decrypted Data: "</span> + decryptedData);

            <span class="hljs-comment">// Asymmetric encryption and decryption</span>
            KeyPair keyPair = generateAsymmetricKeyPair();
            <span class="hljs-keyword">byte</span>[] encryptedDataAsymmetric = encryptAsymmetric(plainText, keyPair.getPublic());
            String decryptedDataAsymmetric = decryptAsymmetric(encryptedDataAsymmetric, keyPair.getPrivate());

            System.out.println(<span class="hljs-string">"\\\\nAsymmetric Encryption and Decryption:"</span>);
            System.out.println(<span class="hljs-string">"Plain Text: "</span> + plainText);
            System.out.println(<span class="hljs-string">"Encrypted Data: "</span> + <span class="hljs-keyword">new</span> String(encryptedDataAsymmetric));
            System.out.println(<span class="hljs-string">"Decrypted Data: "</span> + decryptedDataAsymmetric);
        } <span class="hljs-keyword">catch</span> (NoSuchAlgorithmException | NoSuchPaddingException | InvalidKeyException | BadPaddingException | IllegalBlockSizeException e) {
            e.printStackTrace();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> SecretKey <span class="hljs-title">generateSymmetricKey</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> NoSuchAlgorithmException </span>{
        KeyGenerator keyGenerator = KeyGenerator.getInstance(<span class="hljs-string">"AES"</span>);
        keyGenerator.init(<span class="hljs-number">128</span>);
        <span class="hljs-keyword">return</span> keyGenerator.generateKey();
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">byte</span>[] encryptSymmetric(String plainText, SecretKey secretKey) <span class="hljs-keyword">throws</span> NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance(<span class="hljs-string">"AES"</span>);
        cipher.init(Cipher.ENCRYPT_MODE, secretKey);
        <span class="hljs-keyword">return</span> cipher.doFinal(plainText.getBytes());
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">decryptSymmetric</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] encryptedData, SecretKey secretKey)</span> <span class="hljs-keyword">throws</span> NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException </span>{
        Cipher cipher = Cipher.getInstance(<span class="hljs-string">"AES"</span>);
        cipher.init(Cipher.DECRYPT_MODE, secretKey);
        <span class="hljs-keyword">byte</span>[] decryptedData = cipher.doFinal(encryptedData);
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> String(decryptedData);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> KeyPair <span class="hljs-title">generateAsymmetricKeyPair</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> NoSuchAlgorithmException </span>{
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(<span class="hljs-string">"RSA"</span>);
        keyPairGenerator.initialize(<span class="hljs-number">2048</span>);
        <span class="hljs-keyword">return</span> keyPairGenerator.generateKeyPair();
    }

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">byte</span>[] encryptAsymmetric(String plainText, PublicKey publicKey) <span class="hljs-keyword">throws</span> NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException {
        Cipher cipher = Cipher.getInstance(<span class="hljs-string">"RSA"</span>);
        cipher.init(Cipher.ENCRYPT_MODE, publicKey);
        <span class="hljs-keyword">return</span> cipher.doFinal(plainText.getBytes());
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">decryptAsymmetric</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] encryptedData, PrivateKey privateKey)</span> <span class="hljs-keyword">throws</span> NoSuchAlgorithmException, NoSuchPaddingException, InvalidKeyException, BadPaddingException, IllegalBlockSizeException </span>{
        Cipher cipher = Cipher.getInstance(<span class="hljs-string">"RSA"</span>);
        cipher.init(Cipher.DECRYPT_MODE, privateKey);
        <span class="hljs-keyword">byte</span>[] decryptedData = cipher.doFinal(encryptedData);
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> String(decryptedData);
    }
}
</code></pre>
<h4 id="heading-key-generators-and-factories">Key Generators and Factories</h4>
<p>In Java, you can use key generators and factories to generate and manage cryptographic keys. Key generators provide a way to generate secret keys for symmetric ciphers, while key factories are used to generate public and private keys for asymmetric ciphers.</p>
<p>Here is an example of using key generators and factories in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> javax.crypto.KeyGenerator;
<span class="hljs-keyword">import</span> javax.crypto.SecretKey;
<span class="hljs-keyword">import</span> java.security.NoSuchAlgorithmException;
<span class="hljs-keyword">import</span> java.security.PrivateKey;
<span class="hljs-keyword">import</span> java.security.PublicKey;
<span class="hljs-keyword">import</span> java.security.KeyFactory;
<span class="hljs-keyword">import</span> java.security.spec.PKCS8EncodedKeySpec;
<span class="hljs-keyword">import</span> java.security.spec.X509EncodedKeySpec;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">KeyGenerationExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Generate a secret key for symmetric encryption</span>
            SecretKey secretKey = generateSecretKey();
            System.out.println(<span class="hljs-string">"Symmetric Key: "</span> + Base64.getEncoder().encodeToString(secretKey.getEncoded()));

            <span class="hljs-comment">// Generate public and private keys for asymmetric encryption</span>
            KeyPair keyPair = generateKeyPair();
            PublicKey publicKey = keyPair.getPublic();
            PrivateKey privateKey = keyPair.getPrivate();
            System.out.println(<span class="hljs-string">"Public Key: "</span> + Base64.getEncoder().encodeToString(publicKey.getEncoded()));
            System.out.println(<span class="hljs-string">"Private Key: "</span> + Base64.getEncoder().encodeToString(privateKey.getEncoded()));
        } <span class="hljs-keyword">catch</span> (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> SecretKey <span class="hljs-title">generateSecretKey</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> NoSuchAlgorithmException </span>{
        KeyGenerator keyGenerator = KeyGenerator.getInstance(<span class="hljs-string">"AES"</span>);
        keyGenerator.init(<span class="hljs-number">128</span>);
        <span class="hljs-keyword">return</span> keyGenerator.generateKey();
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> KeyPair <span class="hljs-title">generateKeyPair</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> NoSuchAlgorithmException </span>{
        KeyPairGenerator keyPairGenerator = KeyPairGenerator.getInstance(<span class="hljs-string">"RSA"</span>);
        keyPairGenerator.initialize(<span class="hljs-number">2048</span>);
        <span class="hljs-keyword">return</span> keyPairGenerator.generateKeyPair();
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> PublicKey <span class="hljs-title">getPublicKey</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] publicKeyBytes)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        X509EncodedKeySpec keySpec = <span class="hljs-keyword">new</span> X509EncodedKeySpec(publicKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(<span class="hljs-string">"RSA"</span>);
        <span class="hljs-keyword">return</span> keyFactory.generatePublic(keySpec);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> PrivateKey <span class="hljs-title">getPrivateKey</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] privateKeyBytes)</span> <span class="hljs-keyword">throws</span> Exception </span>{
        PKCS8EncodedKeySpec keySpec = <span class="hljs-keyword">new</span> PKCS8EncodedKeySpec(privateKeyBytes);
        KeyFactory keyFactory = KeyFactory.getInstance(<span class="hljs-string">"RSA"</span>);
        <span class="hljs-keyword">return</span> keyFactory.generatePrivate(keySpec);
    }
}
</code></pre>
<p>By understanding and implementing these cryptographic concepts in Java, you can enhance the security of your Java applications and protect sensitive information effectively.</p>
<h3 id="heading-public-key-infrastructure-pki-in-java">Public Key Infrastructure (PKI) in Java</h3>
<p>When it comes to securing your Java applications, understanding the fundamentals of Public Key Infrastructure (PKI) is essential. </p>
<p>PKI provides a framework for managing keys and certificates. These play a crucial role in establishing secure communication and verifying the authenticity of entities in a networked environment.</p>
<p>In Java, you can leverage the <code>KeyStore</code> and <code>CertStore</code> classes to manage keys and certificates effectively. </p>
<p>The <code>KeyStore</code> class allows you to store and retrieve cryptographic keys, while the <code>CertStore</code> class provides a means to access certificates. </p>
<p>By properly managing keys and certificates, you can ensure the integrity and confidentiality of sensitive information.</p>
<p>Here's an example of using the <code>KeyStore</code> class to load a keystore file and retrieve a private key:</p>
<pre><code class="lang-java">KeyStore keyStore = KeyStore.getInstance(<span class="hljs-string">"JKS"</span>);
<span class="hljs-keyword">char</span>[] keystorePassword = <span class="hljs-string">"password"</span>.toCharArray();
InputStream keystoreStream = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">"keystore.jks"</span>);
keyStore.load(keystoreStream, keystorePassword);

String alias = <span class="hljs-string">"privateKeyAlias"</span>;
<span class="hljs-keyword">char</span>[] keyPassword = <span class="hljs-string">"keyPassword"</span>.toCharArray();
PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, keyPassword);

<span class="hljs-comment">// Use the private key for cryptographic operations</span>
</code></pre>
<p>In this example, we load a keystore file in JKS format, provide the keystore password, and retrieve a private key using its alias and the associated key password. Once you have the private key, you can use it for various cryptographic operations.</p>
<p>Another important aspect of PKI in Java is the usage of tools such as Keytool and Jarsigner. Keytool is a command-line utility that allows you to manage keys and certificates within a keystore. Jarsigner, on the other hand, is used for digitally signing JAR files, ensuring their integrity and authenticity.</p>
<p>Here's an example of using Keytool to generate a key pair and store it in a keystore:</p>
<pre><code class="lang-bash">keytool -genkeypair -<span class="hljs-built_in">alias</span> mykey -keyalg RSA -keystore keystore.jks
</code></pre>
<p>In this command, we generate a key pair using the RSA algorithm and store it in a keystore named "keystore.jks" with an alias "mykey". Keytool will prompt you for additional details such as the keystore password, key password, and the owner's information.</p>
<p>These tools provide essential functionalities for managing keys and certificates, enabling you to establish a secure environment for your Java applications. By incorporating these practices into your development process, you can enhance the security of your applications and protect sensitive data.</p>
<h3 id="heading-authentication-in-java">Authentication in Java</h3>
<p>When it comes to Java security, understanding authentication mechanisms is crucial. Java provides various authentication mechanisms that can be implemented to ensure the safety and protection of applications and data. Let's explore some of these mechanisms and how they can be implemented in Java code.</p>
<h4 id="heading-understanding-authentication-mechanisms-in-java">Understanding Authentication Mechanisms in Java</h4>
<p>In Java, authentication is the process of verifying the identity of a user or entity before granting access to protected resources. Java offers several authentication mechanisms, such as username and password authentication, token-based authentication, and certificate-based authentication.</p>
<p>One common authentication mechanism is username and password authentication. This mechanism involves validating a user's credentials, typically a username and password, to grant access. </p>
<p>To implement username and password authentication in Java, you can use the <code>java.security</code> package and the <code>MessageDigest</code> class to securely hash and compare passwords.</p>
<p>Here's an example code snippet that demonstrates username and password authentication in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.security.MessageDigest;
<span class="hljs-keyword">import</span> java.security.NoSuchAlgorithmException;
<span class="hljs-keyword">import</span> java.util.HashMap;
<span class="hljs-keyword">import</span> java.util.Scanner;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserAuthentication</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> HashMap&lt;String, String&gt; userDatabase = <span class="hljs-keyword">new</span> HashMap&lt;&gt;();

    <span class="hljs-keyword">static</span> {
        <span class="hljs-comment">// Ideally, passwords should be hashed using a secure algorithm with a salt</span>
        userDatabase.put(<span class="hljs-string">"user1"</span>, hashPassword(<span class="hljs-string">"password123"</span>));
        userDatabase.put(<span class="hljs-string">"admin"</span>, hashPassword(<span class="hljs-string">"adminSecure!"</span>));
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> (Scanner scanner = <span class="hljs-keyword">new</span> Scanner(System.in)) {
            System.out.print(<span class="hljs-string">"Enter username: "</span>);
            String username = scanner.nextLine();
            System.out.print(<span class="hljs-string">"Enter password: "</span>);
            String password = scanner.nextLine();

            <span class="hljs-keyword">if</span> (authenticate(username, password)) {
                System.out.println(<span class="hljs-string">"Authentication successful!"</span>);
                <span class="hljs-comment">// Proceed with further operations</span>
            } <span class="hljs-keyword">else</span> {
                System.out.println(<span class="hljs-string">"Authentication failed: Invalid username or password."</span>);
                <span class="hljs-comment">// Handle authentication failure</span>
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">authenticate</span><span class="hljs-params">(String username, String password)</span> </span>{
        <span class="hljs-keyword">return</span> userDatabase.containsKey(username) &amp;&amp; userDatabase.get(username).equals(hashPassword(password));
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">hashPassword</span><span class="hljs-params">(String password)</span> </span>{
        <span class="hljs-keyword">try</span> {
            MessageDigest md = MessageDigest.getInstance(<span class="hljs-string">"SHA-256"</span>);
            <span class="hljs-keyword">byte</span>[] hashedPassword = md.digest(password.getBytes());
            <span class="hljs-keyword">return</span> bytesToHex(hashedPassword);
        } <span class="hljs-keyword">catch</span> (NoSuchAlgorithmException e) {
            e.printStackTrace();
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">null</span>;
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> String <span class="hljs-title">bytesToHex</span><span class="hljs-params">(<span class="hljs-keyword">byte</span>[] bytes)</span> </span>{
        StringBuilder hexString = <span class="hljs-keyword">new</span> StringBuilder();
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">byte</span> b : bytes) {
            String hex = Integer.toHexString(<span class="hljs-number">0xff</span> &amp; b);
            <span class="hljs-keyword">if</span> (hex.length() == <span class="hljs-number">1</span>) {
                hexString.append(<span class="hljs-string">'0'</span>);
            }
            hexString.append(hex);
        }
        <span class="hljs-keyword">return</span> hexString.toString();
    }
}
</code></pre>
<p>In this example, the <code>UserAuthentication</code> class demonstrates username and password authentication. It uses a <code>HashMap</code> to store the user database, where usernames are mapped to their corresponding hashed passwords. The <code>authenticate</code> method checks if the provided username exists in the database and compares the hashed password with the provided password.</p>
<p>Remember, this is a basic example, and in real-world scenarios, you would need to consider additional security measures such as using a salt for password hashing and storing passwords securely.</p>
<p>By implementing these authentication mechanisms in your Java applications, you can ensure the secure verification of user identities and protect sensitive resources.</p>
<h4 id="heading-pluggable-login-modules-flexibility-and-security">Pluggable Login Modules: Flexibility and Security</h4>
<p>In addition to the username and password authentication mechanism, Java provides a flexible and secure approach to authentication through pluggable login modules. Pluggable login modules allow you to define and implement custom authentication mechanisms based on specific requirements.</p>
<p>To implement pluggable login modules in Java, you can utilize the Java Authentication and Authorization Service (JAAS). JAAS provides a framework for authentication and authorization, allowing you to define and configure login modules to authenticate users.</p>
<p>Here's a simplified example code snippet that demonstrates the use of pluggable login modules in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> javax.security.auth.Subject;
<span class="hljs-keyword">import</span> javax.security.auth.login.LoginContext;
<span class="hljs-keyword">import</span> javax.security.auth.login.LoginException;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PluggableAuthentication</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            LoginContext loginContext = <span class="hljs-keyword">new</span> LoginContext(<span class="hljs-string">"SampleLoginModule"</span>);
            loginContext.login();

            Subject subject = loginContext.getSubject();
            <span class="hljs-comment">// Access authenticated subject and perform necessary operations</span>

            loginContext.logout();
        } <span class="hljs-keyword">catch</span> (LoginException e) {
            e.printStackTrace();
            <span class="hljs-comment">// Handle login exception</span>
        }
    }
}
</code></pre>
<p>In this example, the <code>PluggableAuthentication</code> class demonstrates the usage of pluggable login modules. The <code>LoginContext</code> class is responsible for authenticating users using the specified login module, in this case, "SampleLoginModule". Once authenticated, the <code>Subject</code> object can be obtained from the <code>LoginContext</code> to access the authenticated user's information and perform further operations.</p>
<p>By leveraging pluggable login modules, you can customize and extend authentication mechanisms to meet specific security requirements, providing flexibility and enhanced security in your Java applications.</p>
<h4 id="heading-case-study-how-to-implement-username-and-password-authentication">Case Study: How to Implement Username and Password Authentication</h4>
<p>To illustrate the implementation of username and password authentication in Java, let's consider a case study. Suppose you are developing a web application that requires user authentication to access certain resources.</p>
<p>To implement username and password authentication in this case, you can utilize Java's Servlet API and the Java Persistence API (JPA). The Servlet API provides functionality for handling HTTP requests and responses, while JPA allows you to interact with a database and store user information securely.</p>
<p>Here's a high-level example code snippet that demonstrates the implementation of username and password authentication in a web application:</p>
<pre><code class="lang-java"><span class="hljs-meta">@WebServlet("/login")</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LoginServlet</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> </span>{
    <span class="hljs-keyword">private</span> UserService userService;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">init</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> ServletException </span>{
        userService = <span class="hljs-keyword">new</span> UserService(); <span class="hljs-comment">// Initialize the user service</span>
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">protected</span> <span class="hljs-keyword">void</span> <span class="hljs-title">doPost</span><span class="hljs-params">(HttpServletRequest request, HttpServletResponse response)</span> <span class="hljs-keyword">throws</span> ServletException, IOException </span>{
        String username = request.getParameter(<span class="hljs-string">"username"</span>);
        String password = request.getParameter(<span class="hljs-string">"password"</span>);

        <span class="hljs-keyword">if</span> (userService.authenticate(username, password)) {
            <span class="hljs-comment">// Authentication successful</span>
            HttpSession session = request.getSession();
            session.setAttribute(<span class="hljs-string">"username"</span>, username);
            response.sendRedirect(<span class="hljs-string">"dashboard"</span>);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// Authentication failed</span>
            response.sendRedirect(<span class="hljs-string">"login?error=invalid"</span>);
        }
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UserService</span> </span>{
    <span class="hljs-keyword">private</span> UserRepository userRepository;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">UserService</span><span class="hljs-params">()</span> </span>{
        userRepository = <span class="hljs-keyword">new</span> UserRepository(); <span class="hljs-comment">// Initialize the user repository</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">authenticate</span><span class="hljs-params">(String username, String password)</span> </span>{
        User user = userRepository.findByUsername(username);
        <span class="hljs-keyword">if</span> (user != <span class="hljs-keyword">null</span> &amp;&amp; user.getPassword().equals(hashPassword(password))) {
            <span class="hljs-keyword">return</span> <span class="hljs-keyword">true</span>;
        }
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">false</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> String <span class="hljs-title">hashPassword</span><span class="hljs-params">(String password)</span> </span>{
        <span class="hljs-comment">// Implement password hashing algorithm</span>
        <span class="hljs-comment">// Example: return BCrypt.hashpw(password, BCrypt.gensalt());</span>
    }
}
</code></pre>
<p>In this example, the <code>LoginServlet</code> class handles the HTTP POST request for the login page. It retrieves the username and password entered by the user and delegates the authentication process to the <code>UserService</code>. </p>
<p>If the authentication is successful, a session is created, and the user is redirected to the dashboard page. Otherwise, an error parameter is appended to the URL, indicating an invalid login attempt.</p>
<p>The <code>UserService</code> class encapsulates the authentication logic and interacts with the <code>UserRepository</code> to retrieve user information from the database. It compares the hashed password stored in the <code>User</code> entity with the provided password using the implemented password hashing algorithm.</p>
<p>Remember, this is a simplified example, and in a real-world scenario, you would need to consider additional security measures such as implementing secure session management, protecting against brute force attacks, and using stronger password hashing algorithms.</p>
<h2 id="heading-chapter-8-secure-communication-in-java">Chapter 8: Secure Communication in Java</h2>
<p>When it comes to securing client-server communication in Java, there are several protocols and techniques available. Let's explore some of these options:</p>
<h3 id="heading-ssltls-protocols-and-java-implementation">SSL/TLS Protocols and Java Implementation</h3>
<p>To establish a secure connection between a client and a server, the SSL/TLS protocols are commonly used. </p>
<p>In Java, you can utilize the Java Secure Socket Extension (JSSE) to implement SSL/TLS functionality. Here's an example of how to set up a secure connection using JSSE:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> javax.net.ssl.SSLSocket;
<span class="hljs-keyword">import</span> javax.net.ssl.SSLSocketFactory;
<span class="hljs-keyword">import</span> java.io.IOException;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureClient</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            SSLSocketFactory sslSocketFactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
            SSLSocket sslSocket = (SSLSocket) sslSocketFactory.createSocket(<span class="hljs-string">"example.com"</span>, <span class="hljs-number">443</span>);
            <span class="hljs-comment">// Perform secure communication with the server</span>
        } <span class="hljs-keyword">catch</span> (IOException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<p>In this example, we create an <code>SSLSocketFactory</code> and an <code>SSLSocket</code> to establish a secure connection with the server at <code>example.com</code> on port <code>443</code>.</p>
<h3 id="heading-sasl-securing-client-server-communication">SASL: Securing Client-Server Communication</h3>
<p>The Simple Authentication and Security Layer (SASL) is a framework that provides a flexible way to secure client-server communication. It allows clients and servers to negotiate and select authentication mechanisms that suit their requirements. </p>
<p>Here's an example of how to use SASL in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> javax.security.sasl.*;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureClient</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            SaslClient saslClient = Sasl.createSaslClient(<span class="hljs-keyword">new</span> String[]{<span class="hljs-string">"PLAIN"</span>}, <span class="hljs-keyword">null</span>, <span class="hljs-string">""</span>, <span class="hljs-string">"example.com"</span>, <span class="hljs-keyword">null</span>, <span class="hljs-keyword">null</span>);
            <span class="hljs-comment">// Perform secure communication with the server using the SASL client</span>
        } <span class="hljs-keyword">catch</span> (SaslException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<p>In this example, we create a <code>SaslClient</code> using the <code>PLAIN</code> authentication mechanism for secure communication with the server at <code>example.com</code>.</p>
<h3 id="heading-gss-apikerberos-advanced-security-protocols">GSS-API/Kerberos: Advanced Security Protocols</h3>
<p>The Generic Security Service Application Program Interface (GSS-API) provides a framework for implementing advanced security protocols, such as Kerberos, in Java. Kerberos is a widely used authentication protocol that enables secure client-server communication. </p>
<p>Here's an example of how to use GSS-API/Kerberos in Java:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> javax.security.auth.Subject;
<span class="hljs-keyword">import</span> javax.security.auth.login.LoginContext;
<span class="hljs-keyword">import</span> javax.security.auth.login.LoginException;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureClient</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            LoginContext loginContext = <span class="hljs-keyword">new</span> LoginContext(<span class="hljs-string">"KerberosLogin"</span>);
            loginContext.login();
            Subject subject = loginContext.getSubject();
            <span class="hljs-comment">// Perform secure communication with the server using the subject</span>
        } <span class="hljs-keyword">catch</span> (LoginException e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<p>In this example, we use the GSS-API to perform a Kerberos login and obtain a <code>Subject</code> that represents the authenticated client.</p>
<h3 id="heading-access-control-in-java">Access Control in Java</h3>
<p>Java provides several key features and tools to enhance security in your applications. Let's explore the role of <code>SecurityManager</code>, implementing permissions for resource access, and policy files.</p>
<h4 id="heading-role-of-securitymanager-in-java">Role of <code>SecurityManager</code> in Java</h4>
<p>The <code>SecurityManager</code> class plays a vital role in Java security by enforcing fine-grained access control policies. It acts as a gatekeeper, preventing untrusted code from accessing sensitive resources or performing unauthorized operations. </p>
<p>By configuring and utilizing the <code>SecurityManager</code>, you can define and enforce security rules specific to your application's requirements.</p>
<p>Example code:</p>
<pre><code class="lang-java">SecurityManager securityManager = <span class="hljs-keyword">new</span> SecurityManager();
System.setSecurityManager(securityManager);
</code></pre>
<p>By setting a SecurityManager instance, you enable the enforcement of security policies within your Java application.</p>
<h4 id="heading-implement-permissions-for-resource-access">Implement Permissions for Resource Access</h4>
<p>Java's permission model allows you to grant or deny specific permissions to code based on its origin or identity. </p>
<p>By defining and enforcing permissions, you can control which resources or operations a piece of code can access. This helps mitigate the risk of unauthorized access or misuse of sensitive resources.</p>
<p>Example code:</p>
<pre><code class="lang-java">FilePermission filePermission = <span class="hljs-keyword">new</span> FilePermission(<span class="hljs-string">"/path/to/file.txt"</span>, <span class="hljs-string">"read"</span>);
SecurityManager securityManager = System.getSecurityManager();
<span class="hljs-keyword">if</span> (securityManager != <span class="hljs-keyword">null</span>) {
    securityManager.checkPermission(filePermission);
}
</code></pre>
<p>In this example, we define a <code>FilePermission</code> to grant read access to a specific file. The <code>SecurityManager</code>'s <code>checkPermission</code> method ensures that the code has the required permission before accessing the file.</p>
<h4 id="heading-policy-files-defining-and-enforcing-security-policies">Policy Files: Defining and Enforcing Security Policies</h4>
<p>Policy files provide a flexible and configurable way to define and enforce security policies in Java applications. They allow you to specify permissions, code sources, and associated permissions, granting or denying access based on defined rules. </p>
<p>By customizing and managing policy files, you can tailor the security policies to the specific needs of your application.</p>
<p>Example policy file (example.policy):</p>
<pre><code>grant {
    permission java.io.FilePermission <span class="hljs-string">"/path/to/file.txt"</span>, <span class="hljs-string">"read"</span>;
};
</code></pre><p>In this example, we grant read permission to the file "/path/to/file.txt". To enforce this policy file, you can specify it when launching your Java application using the <code>-Djava.security.policy</code> system property:</p>
<pre><code>java -Djava.security.policy=example.policy MyApp
</code></pre><p>By leveraging policy files, you can define and enforce security policies without modifying your application's code.</p>
<h3 id="heading-advanced-java-security-topics">Advanced Java Security Topics</h3>
<p>Java provides various security features and tools to ensure the safety and protection of your applications. Let's explore some important concepts and techniques you can implement in your Java code.</p>
<h4 id="heading-xml-signature-in-java">XML Signature in Java</h4>
<p>XML Signature is a crucial aspect of Java security that allows you to digitally sign XML documents to ensure their integrity and authenticity. By using the Java XML Digital Signature API, you can generate and verify XML signatures. </p>
<p>Here's an example code snippet to demonstrate the usage:</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.io.FileInputStream;
<span class="hljs-keyword">import</span> java.security.KeyStore;
<span class="hljs-keyword">import</span> java.security.PrivateKey;
<span class="hljs-keyword">import</span> java.security.PublicKey;
<span class="hljs-keyword">import</span> java.security.cert.Certificate;
<span class="hljs-keyword">import</span> java.util.Collections;
<span class="hljs-keyword">import</span> javax.xml.crypto.dsig.XMLSignature;
<span class="hljs-keyword">import</span> javax.xml.crypto.dsig.XMLSignatureFactory;
<span class="hljs-keyword">import</span> javax.xml.crypto.dsig.dom.DOMSignContext;
<span class="hljs-keyword">import</span> javax.xml.crypto.dsig.keyinfo.KeyInfo;
<span class="hljs-keyword">import</span> javax.xml.crypto.dsig.keyinfo.KeyValue;
<span class="hljs-keyword">import</span> javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
<span class="hljs-keyword">import</span> javax.xml.crypto.dsig.spec.SignatureMethodParameterSpec;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">XMLSignatureExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Load the keystore</span>
            KeyStore keyStore = KeyStore.getInstance(<span class="hljs-string">"PKCS12"</span>);
            FileInputStream keystoreFile = <span class="hljs-keyword">new</span> FileInputStream(<span class="hljs-string">"keystore.p12"</span>);
            keyStore.load(keystoreFile, <span class="hljs-string">"password"</span>.toCharArray());

            <span class="hljs-comment">// Get the private key and certificate from the keystore</span>
            String alias = keyStore.aliases().nextElement();
            PrivateKey privateKey = (PrivateKey) keyStore.getKey(alias, <span class="hljs-string">"password"</span>.toCharArray());
            Certificate certificate = keyStore.getCertificate(alias);
            PublicKey publicKey = certificate.getPublicKey();

            <span class="hljs-comment">// Create an XMLSignatureFactory</span>
            XMLSignatureFactory signatureFactory = XMLSignatureFactory.getInstance(<span class="hljs-string">"DOM"</span>);

            <span class="hljs-comment">// Create the XMLSignature</span>
            XMLSignature xmlSignature = signatureFactory.newXMLSignature(
                    Collections.singletonList(signatureFactory.newReference(<span class="hljs-string">"#content"</span>, <span class="hljs-comment">// Reference URI</span>
                            signatureFactory.newDigestMethod(<span class="hljs-string">"&lt;http://www.w3.org/2001/04/xmlenc#sha256&gt;"</span>, <span class="hljs-keyword">null</span>))),
                    signatureFactory.newKeyInfo(Collections.singletonList(signatureFactory.newX509Data(Collections.singletonList(certificate)))),
                    signatureFactory.newSignatureMethod(<span class="hljs-string">"&lt;http://www.w3.org/2001/04/xmldsig-more#rsa-sha256&gt;"</span>, <span class="hljs-keyword">null</span>));

            <span class="hljs-comment">// Create the DOMSignContext</span>
            DOMSignContext signContext = <span class="hljs-keyword">new</span> DOMSignContext(privateKey, document.getDocumentElement());

            <span class="hljs-comment">// Marshal the XMLSignature into the DOM tree</span>
            xmlSignature.sign(signContext);
        } <span class="hljs-keyword">catch</span> (Exception e) {
            e.printStackTrace();
        }
    }
}
</code></pre>
<h4 id="heading-deprecated-security-apis-to-avoid">Deprecated Security APIs to Avoid</h4>
<p>Java has deprecated certain security APIs due to their vulnerabilities or outdated functionality. It is important to avoid using these deprecated APIs and migrate to the recommended alternatives. </p>
<p>Here are a few examples of deprecated security APIs and their recommended replacements:</p>
<ul>
<li><strong><code>java.security.KeyStore</code></strong>: Deprecated in favor of <code>java.security.KeyStore.Builder</code>.</li>
<li><strong><code>java.security.SecureRandom</code></strong>: Deprecated in favor of <code>java.security.SecureRandom.getInstanceStrong()</code> or <code>java.security.SecureRandom.getInstance()</code>.</li>
<li><strong><code>java.security.KeyPairGenerator</code></strong>: Deprecated in favor of <code>java.security.KeyPairGenerator.getInstance()</code>.</li>
</ul>
<p>Always refer to the Java documentation for the complete list of deprecated security APIs and their recommended alternatives.</p>
<h4 id="heading-security-tools-and-commands-in-java">Security Tools and Commands in Java</h4>
<p>Java provides various security tools and commands that can assist you in analyzing and enhancing the security of your applications. </p>
<p>Here are a few commonly used tools and commands:</p>
<ul>
<li><strong><code>jarsigner</code></strong>: The <code>jarsigner</code> tool allows you to digitally sign JAR files to ensure their integrity and authenticity.</li>
<li><strong><code>keytool</code></strong>: The <code>keytool</code> command-line utility enables you to manage cryptographic keys and certificates in a Java KeyStore.</li>
<li><strong><code>javadoc</code></strong>: The <code>javadoc</code> tool generates API documentation, including security-related APIs, from Java source code.</li>
<li><strong><code>jps</code></strong>: The <code>jps</code> command-line utility displays information about Java processes running on a system, including their security settings.</li>
<li><strong><code>jinfo</code></strong>: The <code>jinfo</code> command-line utility provides configuration information for a running Java process, including security-related properties.</li>
</ul>
<p>These tools and commands can be valuable in securing your Java applications and ensuring proper configuration and management of security-related components.</p>
<p>Remember to always refer to the official Java documentation and stay updated with the latest security practices and recommendations. Implementing robust security measures and regularly reviewing your code for potential vulnerabilities are essential for maintaining a secure Java environment.</p>
<h3 id="heading-java-security-in-practice">Java Security in Practice</h3>
<p>Java security plays a crucial role in today's digital landscape, ensuring the safety and protection of applications and sensitive data. Let's explore some real-world applications where Java security is prominently used and discuss case studies in the banking and e-commerce sectors.</p>
<h4 id="heading-real-world-applications-of-java-security">Real-World Applications of Java Security</h4>
<p>Java security is extensively utilized in various real-world applications, including banking systems, e-commerce platforms, and government services. </p>
<p>For example, in the banking sector, Java security is crucial for ensuring secure online transactions, protecting customer data, and preventing unauthorized access. Robust authentication mechanisms, encryption algorithms, and secure coding practices are employed to maintain the integrity and confidentiality of financial data.</p>
<p>In e-commerce platforms, Java security plays a vital role in safeguarding sensitive customer information, such as credit card details and personal data. Strict access control, secure communication protocols, and secure coding practices are implemented to prevent data breaches and protect customer privacy.</p>
<p>Let's explore two case studies that illustrate the practical implementation of Java security in the banking and e-commerce sectors.</p>
<h4 id="heading-case-study-banking-application">Case Study: Banking Application</h4>
<p>In a banking application, Java security is crucial for protecting customer accounts, preventing fraudulent activities, and ensuring the confidentiality of financial transactions. </p>
<p>To achieve this, the application incorporates several security measures:</p>
<ul>
<li><strong>Secure Authentication</strong>: The banking application employs strong authentication mechanisms to verify the identity of users. Multi-factor authentication, such as combining passwords with biometric data, adds an extra layer of security.</li>
</ul>
<p>Example Code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (authenticate(username, password)) {
    <span class="hljs-comment">// User authenticated successfully</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Invalid credentials, authentication failed</span>
}
</code></pre>
<ul>
<li><strong>Secure Communication</strong>: The application uses secure communication protocols, such as HTTPS, to encrypt data transmission between the client and the server. This prevents eavesdropping and ensures the integrity of sensitive information.</li>
</ul>
<p>Example Code:</p>
<pre><code class="lang-java">URL url = <span class="hljs-keyword">new</span> URL(<span class="hljs-string">"&lt;https://bankingapi.com&gt;"</span>);
HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
<span class="hljs-comment">// Perform secure communication with the banking API</span>
</code></pre>
<ul>
<li><strong>Secure Data Storage</strong>: Customer data, including account details and transaction history, is securely stored using encryption techniques. Strong encryption algorithms and proper key management ensure the confidentiality of sensitive data.</li>
</ul>
<p>Example Code:</p>
<pre><code class="lang-java">String encryptedData = encrypt(data, encryptionKey);
<span class="hljs-comment">// Store the encrypted data securely</span>
</code></pre>
<h4 id="heading-case-study-e-commerce-platform">Case Study: E-commerce Platform</h4>
<p>In an e-commerce platform, Java security is vital for protecting customer data, securing payment transactions, and preventing unauthorized access to user accounts. The platform incorporates various security measures to ensure a safe and trustworthy shopping experience.</p>
<ul>
<li><strong>Secure Payment Processing</strong>: The e-commerce platform integrates with secure payment gateways, employing encryption and tokenization techniques to protect sensitive payment information. This ensures that customer payment details are securely transmitted and stored.</li>
</ul>
<p>Example Code:</p>
<pre><code class="lang-java">PaymentGateway paymentGateway = <span class="hljs-keyword">new</span> PaymentGateway();
PaymentResponse response = paymentGateway.processPayment(order, creditCard);
<span class="hljs-comment">// Securely process the payment transaction</span>
</code></pre>
<ul>
<li><strong>Secure User Account Management</strong>: The platform enforces strong password policies, implements secure password storage techniques such as hashing and salting, and provides multi-factor authentication options to protect user accounts from unauthorized access.</li>
</ul>
<p>Example Code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (authenticate(username, password)) {
    <span class="hljs-comment">// User authenticated successfully</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Invalid credentials, authentication failed</span>
}
</code></pre>
<ul>
<li><strong>Secure Session Management</strong>: The e-commerce platform ensures secure session management by generating unique session IDs, implementing session timeouts, and securely storing session data to prevent session hijacking attacks.</li>
</ul>
<p>Example Code:</p>
<pre><code class="lang-java">String sessionId = generateSessionId();
SessionManager.setSessionData(sessionId, userData);
<span class="hljs-comment">// Manage user sessions securely</span>
</code></pre>
<p>By implementing these Java security measures, banking and e-commerce applications can provide a secure and trustworthy environment for their users. Remember to adapt these examples to your specific application requirements and consider additional security measures based on industry standards and best practices.</p>
<h3 id="heading-java-security-for-developers">Java Security for Developers</h3>
<p>When it comes to writing secure code in Java, it is important to follow best practices to ensure the safety and protection of your applications. By avoiding common security pitfalls and enhancing your skills through developer security training, you can create robust and secure Java applications. Let's explore these concepts in more detail.</p>
<h4 id="heading-how-to-write-secure-code-best-practices">How to Write Secure Code: Best Practices</h4>
<p>Writing secure code involves adopting best practices that help mitigate security risks. Here are some key practices to consider:</p>
<p><strong>Input Validation</strong>: Always validate and sanitize user input to prevent common vulnerabilities such as SQL injection or cross-site scripting (XSS) attacks. Use built-in Java libraries or frameworks to handle input validation effectively.</p>
<p>Example Code:</p>
<pre><code class="lang-java">String sanitizedInput = sanitizeUserInput(userInput);
<span class="hljs-comment">// Use sanitizedInput securely to prevent vulnerabilities</span>
</code></pre>
<p><strong>Secure Communication</strong>: Utilize secure communication protocols, such as HTTPS, to encrypt data transmitted between the client and the server. This ensures the confidentiality and integrity of sensitive information.</p>
<p>Example Code:</p>
<pre><code class="lang-java">URLConnection connection = url.openConnection();
<span class="hljs-keyword">if</span> (connection <span class="hljs-keyword">instanceof</span> HttpsURLConnection) {
    ((HttpsURLConnection) connection).setHostnameVerifier((hostname, session) -&gt; <span class="hljs-keyword">true</span>);
    ((HttpsURLConnection) connection).setSSLSocketFactory(trustAllCertificates());
}
</code></pre>
<p><strong>Authentication and Authorization</strong>: Implement strong authentication mechanisms to verify the identity of users and grant appropriate access privileges. Use secure algorithms for password hashing and consider multi-factor authentication for enhanced security.</p>
<p>Example Code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (authenticate(username, password)) {
    <span class="hljs-comment">// Perform necessary operations</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Handle authentication failure</span>
}
</code></pre>
<p><strong>Error Handling</strong>: Handle errors securely by providing informative error messages to users while avoiding exposing sensitive information that could be exploited by attackers. Log errors appropriately for monitoring and debugging purposes.</p>
<p>Example Code:</p>
<pre><code class="lang-java"><span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Perform operations</span>
} <span class="hljs-keyword">catch</span> (Exception e) {
    LOGGER.log(Level.SEVERE, <span class="hljs-string">"An error occurred"</span>, e);
}
</code></pre>
<p><strong>Secure Session Management</strong>: Implement secure session management techniques, such as using secure tokens or session IDs, to prevent session hijacking or fixation attacks. Set appropriate session timeouts and invalidate sessions after logout.</p>
<p>Example Code:</p>
<pre><code class="lang-java">HttpSession session = request.getSession();
session.setAttribute(<span class="hljs-string">"user"</span>, user);
session.setMaxInactiveInterval(<span class="hljs-number">1800</span>); <span class="hljs-comment">// Set session timeout to 30 minutes</span>
</code></pre>
<h4 id="heading-common-security-pitfalls-and-how-to-avoid-them">Common Security Pitfalls and How to Avoid Them</h4>
<p>To write secure Java code, it is crucial to be aware of common security pitfalls and take steps to avoid them. Here are some pitfalls to watch out for:</p>
<p><strong>Insecure Direct Object References</strong>: Avoid exposing internal object references directly in URLs or hidden fields, as it can lead to unauthorized access to sensitive data. Use indirect references or access control mechanisms to protect confidential information.</p>
<p>Example Code:</p>
<pre><code class="lang-java">String productId = request.getParameter(<span class="hljs-string">"productId"</span>);
Product product = getProductById(productId);
<span class="hljs-keyword">if</span> (product != <span class="hljs-keyword">null</span> &amp;&amp; product.isAvailable()) {
    <span class="hljs-comment">// Display product details</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Handle invalid or unavailable product</span>
}
</code></pre>
<p><strong>Cross-Site Scripting (XSS) Attacks</strong>: Prevent XSS attacks by properly encoding user-generated content and validating input. Utilize frameworks or libraries that automatically handle HTML encoding to mitigate this risk.</p>
<p>Example Code:</p>
<pre><code class="lang-java">String encodedContent = HtmlUtils.htmlEscape(userInput);
<span class="hljs-comment">// Use encodedContent safely to prevent XSS attacks</span>
</code></pre>
<p><strong>Insecure Cryptography</strong>: Avoid using weak or outdated cryptographic algorithms, as they can be vulnerable to attacks. Utilize the cryptographic functionalities provided by Java, such as AES or RSA, with secure key management practices.</p>
<p>Example Code:</p>
<pre><code class="lang-java">Cipher cipher = Cipher.getInstance(<span class="hljs-string">"AES/CBC/PKCS5Padding"</span>);
cipher.init(Cipher.ENCRYPT_MODE, secretKey);
<span class="hljs-keyword">byte</span>[] encryptedData = cipher.doFinal(data);
</code></pre>
<p><strong>Code Injection</strong>: Prevent code injection attacks, such as SQL injection or OS command injection, by utilizing prepared statements or parameterized queries. Avoid constructing queries or commands by concatenating user input.</p>
<p>Example Code:</p>
<pre><code class="lang-java">PreparedStatement statement = connection.prepareStatement(<span class="hljs-string">"SELECT * FROM users WHERE username = ?"</span>);
statement.setString(<span class="hljs-number">1</span>, username);
ResultSet resultSet = statement.executeQuery();
</code></pre>
<h4 id="heading-here-is-an-example-of-an-insecure-code-and-the-solution-to-it">Here is an example of an insecure code and the solution to it:</h4>
<p>Here’s an example of a Java Servlet that has several security issues related to Insecure Cryptography, Cross-Site Scripting (XSS) Attacks, and Insecure Direct Object References:</p>
<pre><code><span class="hljs-keyword">import</span> javax.crypto.Cipher;
<span class="hljs-keyword">import</span> javax.crypto.spec.SecretKeySpec;
<span class="hljs-keyword">import</span> javax.servlet.http.*;
<span class="hljs-keyword">import</span> java.security.MessageDigest;
<span class="hljs-keyword">import</span> java.sql.*;

public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InsecureServlet</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> </span>{

    private <span class="hljs-keyword">static</span> final <span class="hljs-built_in">String</span> SECRET_KEY = <span class="hljs-string">"ThisIsASecretKey"</span>;

    protected <span class="hljs-keyword">void</span> doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        <span class="hljs-built_in">String</span> username = request.getParameter(<span class="hljs-string">"username"</span>);
        <span class="hljs-built_in">String</span> password = request.getParameter(<span class="hljs-string">"password"</span>);

        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Insecure Direct Object Reference: Using user-supplied input directly</span>
            <span class="hljs-built_in">String</span> query = <span class="hljs-string">"SELECT * FROM users WHERE username = '"</span> + username + <span class="hljs-string">"'"</span>;

            <span class="hljs-comment">// Insecure Cryptography: Using MD5, which is considered insecure</span>
            MessageDigest md = MessageDigest.getInstance(<span class="hljs-string">"MD5"</span>);
            byte[] hashedPassword = md.digest(password.getBytes());
            <span class="hljs-built_in">String</span> hashedPasswordStr = <span class="hljs-keyword">new</span> <span class="hljs-built_in">String</span>(hashedPassword);

            <span class="hljs-keyword">if</span> (query.equals(hashedPasswordStr)) {
                <span class="hljs-comment">// Cross-Site Scripting (XSS) Attacks: Directly outputting user-supplied input without sanitization</span>
                response.getWriter().println(<span class="hljs-string">"Welcome, "</span> + username + <span class="hljs-string">"!"</span>);
            } <span class="hljs-keyword">else</span> {
                response.getWriter().println(<span class="hljs-string">"Invalid username or password."</span>);
            }
        } <span class="hljs-keyword">catch</span> (Exception e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ServletException(e);
        }
    }
}
</code></pre><p>In this code:</p>
<ol>
<li><strong>Insecure Direct Object References</strong>: The code constructs an SQL query using the user-supplied <code>username</code> directly, which can lead to SQL Injection attacks if the <code>username</code> is not properly sanitized.</li>
<li><strong>Insecure Cryptography</strong>: The code uses MD5 to hash the password, which is considered insecure due to its vulnerability to collision attacks. A stronger algorithm like bcrypt or scrypt should be used instead.</li>
<li><strong>Cross-Site Scripting (XSS) Attacks</strong>: The code directly outputs the user-supplied <code>username</code> to the response without any sanitization or encoding, which can lead to XSS attacks if the <code>username</code> contains malicious scripts.</li>
</ol>
<h4 id="heading-here-is-the-solution-to-it">Here is the solution to it:</h4>
<pre><code><span class="hljs-keyword">import</span> javax.crypto.SecretKeyFactory;
<span class="hljs-keyword">import</span> javax.crypto.spec.PBEKeySpec;
<span class="hljs-keyword">import</span> javax.servlet.http.*;
<span class="hljs-keyword">import</span> java.security.NoSuchAlgorithmException;
<span class="hljs-keyword">import</span> java.security.spec.InvalidKeySpecException;
<span class="hljs-keyword">import</span> java.sql.*;
<span class="hljs-keyword">import</span> java.util.Base64;

public <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SecureServlet</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HttpServlet</span> </span>{

    private <span class="hljs-keyword">static</span> final <span class="hljs-built_in">String</span> SECRET_KEY = <span class="hljs-string">"ThisIsASecretKey"</span>;

    protected <span class="hljs-keyword">void</span> doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        <span class="hljs-built_in">String</span> username = request.getParameter(<span class="hljs-string">"username"</span>);
        <span class="hljs-built_in">String</span> password = request.getParameter(<span class="hljs-string">"password"</span>);

        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Use prepared statement to prevent SQL Injection</span>
            <span class="hljs-built_in">String</span> query = <span class="hljs-string">"SELECT password FROM users WHERE username = ?"</span>;
            PreparedStatement pstmt = connection.prepareStatement(query);
            pstmt.setString(<span class="hljs-number">1</span>, username);
            ResultSet rs = pstmt.executeQuery();

            <span class="hljs-keyword">if</span> (rs.next()) {
                <span class="hljs-built_in">String</span> storedPassword = rs.getString(<span class="hljs-string">"password"</span>);

                <span class="hljs-comment">// Use bcrypt for password hashing</span>
                byte[] salt = <span class="hljs-keyword">new</span> byte[<span class="hljs-number">16</span>];
                PBEKeySpec spec = <span class="hljs-keyword">new</span> PBEKeySpec(password.toCharArray(), salt, <span class="hljs-number">65536</span>, <span class="hljs-number">128</span>);
                SecretKeyFactory skf = SecretKeyFactory.getInstance(<span class="hljs-string">"PBKDF2WithHmacSHA1"</span>);
                byte[] hash = skf.generateSecret(spec).getEncoded();
                <span class="hljs-built_in">String</span> hashedPassword = Base64.getEncoder().encodeToString(hash);

                <span class="hljs-keyword">if</span> (storedPassword.equals(hashedPassword)) {
                    <span class="hljs-comment">// Escape user-supplied input to prevent XSS</span>
                    <span class="hljs-built_in">String</span> safeUsername = org.apache.commons.lang3.StringEscapeUtils.escapeHtml4(username);
                    response.getWriter().println(<span class="hljs-string">"Welcome, "</span> + safeUsername + <span class="hljs-string">"!"</span>);
                } <span class="hljs-keyword">else</span> {
                    response.getWriter().println(<span class="hljs-string">"Invalid username or password."</span>);
                }
            }
        } <span class="hljs-keyword">catch</span> (NoSuchAlgorithmException | InvalidKeySpecException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> ServletException(e);
        }
    }
}
</code></pre><p>In this revised code, we use a <code>PreparedStatement</code> to prevent SQL Injection attacks. We replace MD5 with bcrypt for password hashing. And we escape the <code>username</code> using <code>StringEscapeUtils.escapeHtml4()</code> from Apache Commons Lang to prevent XSS attacks. </p>
<p>Note that this is a simplified example and real-world applications may have additional complexities and security considerations. Always follow best practices for secure coding to protect your application from these and other security vulnerabilities. </p>
<p>Also, remember to never expose sensitive information like secret keys in your code as done in this example. It’s always recommended to store such information in secure and encrypted environment variables or configuration files.</p>
<h4 id="heading-developer-security-training-enhancing-skills">Developer Security Training: Enhancing Skills</h4>
<p>Continuously improving your security skills through developer security training is crucial for writing secure Java code. </p>
<p>Here are some steps you can take to enhance your skills:</p>
<ol>
<li><strong>Stay Updated</strong>: Keep yourself informed about the latest security threats, vulnerabilities, and best practices by following reputable security resources, attending security conferences, and participating in security-focused communities.</li>
<li><strong>Training Programs</strong>: Explore security training programs and certifications specifically designed for developers. These programs provide in-depth knowledge and practical guidance on secure coding practices, vulnerability assessment, and secure software development.</li>
<li><strong>Code Reviews</strong>: Engage in peer code reviews that include security-focused analysis. Collaborating with experienced developers can help identify potential security weaknesses and learn from their expertise.</li>
<li><strong>Security Tools</strong>: Utilize security analysis tools, such as static code analysis or vulnerability scanners, to identify potential security vulnerabilities in your code. These tools provide automated checks and recommendations for improvement.</li>
</ol>
<p>By following these practices, avoiding common pitfalls, and continuously enhancing your security skills, you can write secure Java code that protects your applications and user data.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>In conclusion, this book has equipped you with advanced Java programming skills crucial for any software engineer. </p>
<p>You've covered key topics ranging from unit testing and debugging to Java security, preparing you to handle real-world software development challenges. </p>
<p>Your journey through these chapters has enhanced your technical expertise, making you adept at creating efficient, secure, and robust software solutions.</p>
<p>Your newfound knowledge opens up a world of opportunities, from advancing in your current role to aspiring for senior developer positions or embarking on your own tech venture. With Java's role in AI, big data, and cloud computing, your skills are more relevant than ever.</p>
<p>As you step forward, remember that mastering Java is about applying these concepts to develop innovative solutions. Continue to grow, adapt to new technologies, and let your passion for programming drive you.</p>
<p>Now, with both the knowledge and confidence, you're ready to make your mark in the world of Java programming. Whether contributing to open-source projects, seeking Java certification, or innovating in your professional endeavors, you are well-prepared for the challenges and opportunities ahead. The path from learning to leading in the Java community awaits.</p>
<h3 id="heading-resources">Resources</h3>
<p>If you're keen on furthering your Java knowledge, here's a guide to help you <a target="_blank" href="https://join.lunartech.ai/java-fundamentals">conquer Java and launch your coding career</a>. It's perfect for those interested in AI and machine learning, focusing on effective use of data structures in coding. This comprehensive program covers essential data structures, algorithms, and includes mentorship and career support.</p>
<p>Additionally, for more practice in data structures, you can explore these resources:</p>
<ol>
<li><strong><a target="_blank" href="https://join.lunartech.ai/six-figure-data-science-bootcamp">Java Data Structures Mastery - Ace the Coding Interview</a></strong>: A free eBook to advance your Java skills, focusing on data structures for enhancing interview and professional skills.</li>
<li><a target="_blank" href="https://join.lunartech.ai/java-fundamentals"><strong>Foundations of Java Data Structures - Your Coding Catalyst</strong></a>: Another free eBook, diving into Java essentials, object-oriented programming, and AI applications.</li>
</ol>
<p>Visit LunarTech's website for these resources and more information on the <a target="_blank" href="https://lunartech.ai/">bootcamp</a>.</p>
<h3 id="heading-connect-with-me"><strong>Connect with Me:</strong></h3>
<ul>
<li><a target="_blank" href="https://ca.linkedin.com/in/vahe-aslanyan">Follow me on LinkedIn for a ton of Free Resources in CS, ML and AI</a></li>
<li><a target="_blank" href="https://vaheaslanyan.com/">Visit my Personal Website</a></li>
<li>Subscribe to my <a target="_blank" href="https://tatevaslanyan.substack.com/">The Data Science and AI Newsletter</a></li>
</ul>
<h2 id="heading-about-the-author"><strong>About the Author</strong></h2>
<p>I'm Vahe Aslanyan, specializing in the world of computer science, data science, and artificial intelligence. Explore my work at <a target="_blank" href="https://www.vaheaslanyan.com/">vaheaslanyan.com</a>. My expertise encompasses robust full-stack development and the strategic enhancement of AI products, with a focus on inventive problem-solving.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://vaheaslanyan.com/">https://vaheaslanyan.com/</a></div>
<p>My experience includes spearheading the launch of a prestigious data science bootcamp, an endeavor that put me at the forefront of industry innovation. I've consistently aimed to revolutionize technical education, striving to set a new, universal standard.</p>
<p>As we close this book, I extend my sincere thanks for your focused engagement. Imparting my professional insights through this book has been a journey of professional reflection. Your participation has been invaluable. I anticipate these shared experiences will significantly contribute to your growth in the dynamic field of technology.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Gitting Things Done – A Visual and Practical Guide to Git [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ Introduction Git is awesome. Most software developers use Git on a daily basis. But how many truly understand Git? Do you feel like you know what's going on under the hood as you use Git to perform various tasks? For example, what happens when you us... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/gitting-things-done-book/</link>
                <guid isPermaLink="false">66c17c2bea5637f064224a06</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Git ]]>
                    </category>
                
                    <category>
                        <![CDATA[ GitHub ]]>
                    </category>
                
                    <category>
                        <![CDATA[ version control ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Omer Rosenbaum ]]>
                </dc:creator>
                <pubDate>Mon, 08 Jan 2024 17:12:21 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/12/Gitting-Things-Done-Cover-with-Photo.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <h2 id="heading-introduction">Introduction</h2>
<p>Git is awesome.</p>
<p>Most software developers use Git on a daily basis. But how many truly understand Git? Do <em>you</em> feel like you know what's going on under the hood as you use Git to perform various tasks?</p>
<p>For example, what happens when you use <code>git commit</code>? What is stored between commits? Is it just a diff between the current and previous commit? If so, how is the diff encoded? Or is an entire snapshot of the repository stored each time?</p>
<p>Most people who use Git don't know the answers to the questions posed above. But does it really matter? Do you really have to know all of those things?</p>
<p>I'd argue that it does matter. As professionals, we should strive to understand the tools we use, especially if we use them all the time, like Git.</p>
<p>Even more acutely, I've found that understanding how Git actually works is <strong>useful</strong> in many scenarios — whether resolving merge conflicts, looking to conduct an interesting rebase, or even just when something goes slightly wrong. </p>
<p>So many times have I received questions about Git from experienced, highly skilled software engineers. I have seen wonderful developers react in fear when something happened in their commit history, and they just didn't know what to do. It doesn't have to be this way.</p>
<p>By reading this book, you will gain a new perspective of Git. You will feel <strong>confident</strong> when working with Git, and you will <strong>understand</strong> Git's underlying mechanisms, at least those that are useful to understand. You will <em>Git</em> it. You will be <em>Gitting things done</em>.</p>
<h1 id="heading-table-of-contents">Table of Contents</h1>
<ul>
<li><a class="post-section-overview" href="#heading-introduction">Introduction</a></li>
<li><a class="post-section-overview" href="#heading-part-1-main-objects-and-introducing-changes">Part 1 - Main Objects and Introducing Changes</a><ul>
<li><a class="post-section-overview" href="#heading-chapter-1-git-objects">Chapter 1 - Git Objects</a></li>
<li><a class="post-section-overview" href="#heading-chapter-2-branches-in-git">Chapter 2 - Branches in Git</a></li>
<li><a class="post-section-overview" href="#heading-chapter-3-how-to-record-changes-in-git">Chapter 3 - How to Record Changes in Git</a></li>
<li><a class="post-section-overview" href="#heading-chapter-4-how-to-create-a-repo-from-scratch">Chapter 4 - How to Create a Repo From Scratch</a></li>
<li><a class="post-section-overview" href="#heading-chapter-5-how-to-work-with-branches-in-git-under-the-hood">Chapter 5 - How to Work with Branches in Git — Under the Hood</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-part-2-branching-and-integrating-changes">Part 2 - Branching and Integrating Changes</a><ul>
<li><a class="post-section-overview" href="#heading-chapter-6-diffs-and-patches">Chapter 6 - Diffs and Patches</a></li>
<li><a class="post-section-overview" href="#heading-chapter-7-understanding-git-merge">Chapter 7 - Understanding Git Merge</a></li>
<li><a class="post-section-overview" href="#heading-chapter-8-understanding-git-rebase">Chapter 8 - Understanding Git Rebase</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-part-3-undoing-changes">Part 3 - Undoing Changes</a><ul>
<li><a class="post-section-overview" href="#heading-chapter-9-git-reset">Chapter 9 - Git Reset</a></li>
<li><a class="post-section-overview" href="#heading-chapter-10-additional-tools-for-undoing-changes">Chapter 10 - Additional Tools for Undoing Changes</a></li>
<li><a class="post-section-overview" href="#heading-chapter-11-exercises">Chapter 11 - Exercises</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-part-4-amazing-and-useful-git-tools">Part 4 - Amazing and Useful Git Tools</a><ul>
<li><a class="post-section-overview" href="#heading-chapter-12-git-log">Chapter 12 - Git Log</a></li>
<li><a class="post-section-overview" href="#heading-chapter-13-git-bisect">Chapter 13 - Git Bisect</a></li>
<li><a class="post-section-overview" href="#heading-chapter-14-other-useful-commands">Chapter 14 - Other Useful Commands</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-summary">Summary</a></li>
<li><a class="post-section-overview" href="#heading-appendixes">Appendixes</a></li>
</ul>
<h2 id="heading-who-is-this-book-for">Who Is This Book For?</h2>
<p>Any software developer who wants to deepen their knowledge about Git.</p>
<p>If you are experienced with Git - I am sure you will be able to deepen your knowledge. Even if you are new to Git - I will start with an overview of the mechanisms of Git, and the terms used throughout this book.</p>
<p>This book is for you. I wrote it so you can learn more about Git, and also come to appreciate, or even love Git.</p>
<p>You will also notice that I use a casual style throughout the book. I believe that learning Git should be insightful and fun. Learning new things is always hard, and I felt like writing in a less casual style wouldn't really make a good service. And as I already mentioned - this book is for you.</p>
<h2 id="heading-who-am-i">Who Am I?</h2>
<p>This book is about you, and your journey with Git. But I would like to tell you a bit about why I think I can contribute to your journey.</p>
<p>I am the CTO and one of the co-founders of <a target="_blank" href="https://swimm.io">Swimm.io</a>, a knowledge management tool for code. Part of what we do is linking parts from code in Git repositories to parts of the documentation, and then tracking changes in the repository to update the documentation if needed. </p>
<p>At Swimm, I got to dissect parts of Git, understand its underlying mechanisms and also gain intuition about why Git is implemented the way it is.</p>
<p>Before founding Swimm I practiced teaching in many different environments - among them, managing the Cyber track of Israel Tech Challenge, founding Check Point Security Academy, and writing a full text book.</p>
<p>This book is my attempt to make the most of both worlds - my teaching experience as well as my in-depth hands-on experience with Git, and give you the best learning experience I can.</p>
<h2 id="heading-the-approach-of-this-book">The Approach of This Book</h2>
<p>This is definitely not the first book about Git. When sitting down to write it, I had three principles in mind.</p>
<ol>
<li><strong>Practical</strong> - in this book, you will learn how to accomplish things in Git. How to introduce changes, how to undo them, and how to fix things when they go wrong. You will understand how Git works not just for the sake of understanding, but with a practical mindset. I sometimes refer to this as the "practicality principle" - which guides me in deciding whether to include certain topics, and to what extent.</li>
<li><strong>In depth</strong> - you will dive deep into Git's way of operating, to understand its mechanisms. You will build your understanding gradually, and always link your knowledge to real scenarios you might face in your work. In order to achieve an in-depth understanding, I almost always prefer the command line over graphical interfaces, so you can really see what commands are running.</li>
<li><strong>Visual</strong> - as I strive to provide you with intuition, the chapters will be accompanied by visual aids.</li>
</ol>
<h2 id="heading-why-is-this-book-publicly-available">Why Is This Book Publicly Available?</h2>
<p>I think everyone should have access to high quality content about Git, and I'd like this book to get to as many people as possible.</p>
<p>If you would like to support this book, you are welcome to buy the <a target="_blank" href="https://www.amazon.com/dp/B0CQXTJ5V5">Paperback version</a>, an <a target="_blank" href="https://www.buymeacoffee.com/omerr/e/197232">E-Book version</a>, or <a target="_blank" href="https://www.buymeacoffee.com/omerr">buy me a coffee</a>. Thank you!</p>
<h2 id="heading-accompanying-videos">Accompanying Videos</h2>
<p>I have covered many topics from this book on my YouTube channel - Brief (<a target="_blank" href="https://www.youtube.com/@BriefVid">https://www.youtube.com/@BriefVid</a>). You are welcome to check them out as well.</p>
<h2 id="heading-get-your-hands-dirty">Get Your Hands Dirty</h2>
<p>Throughout this book, I will mostly use the second person singular - and directly write to <em>you</em>. I will ask <em>you</em> to get your hands dirty, run the commands yourself, so you actually get to <em>feel</em> what it's like to use do things with Git, not just read about it.</p>
<h2 id="heading-gits-feelings">Git's Feelings</h2>
<p>Throughout the book, I sometimes refer to Git with words such as "believes", "thinks", or "wants". As you may argue, Git is not a human, and it doesn't have feelings or beliefs. Well, that's true, but in order for us to enjoy playing around with Git, and to help you enjoy reading (and me writing) this book, I feel like referring to Git as more than just code makes it all so much more enjoyable.</p>
<h2 id="heading-my-setup">My Setup</h2>
<p>I will include screenshots. There's no need for your setup to match mine, but if you're curious about my setup, then:</p>
<ul>
<li>I am using Ubuntu 20.04 (WSL).</li>
<li>For my terminal, I use <a target="_blank" href="https://ohmyz.sh/">Oh My Zsh</a></li>
<li>I also use plugins for Oh My Zsh, you can <a target="_blank" href="https://www.freecodecamp.org/news/jazz-up-your-zsh-terminal-in-seven-steps-a-visual-guide-e81a8fd59a38/">follow this tutorial on freeCodeCamp</a>.</li>
<li><a target="_blank" href="https://github.com/mlange-42/git-graph">git-graph (my alias is <code>gg</code>)</a></li>
</ul>
<h2 id="heading-feedback-is-welcome">Feedback Is Welcome</h2>
<p>This book has been created to help you and people like you learn, understand Git, and apply that knowledge in real life. </p>
<p>Right from the beginning, I asked for feedback and was lucky to receive it from great people (see <a class="post-section-overview" href="#heading-acknowledgements">Acknowledgments</a>) to make sure the book achieves these goals. If you liked something about this book, felt that something was missing, or that something needed improvement - I would love to hear from you. Please reach out at <a target="_blank" href="mailto:gitting.things@gmail.com">gitting.things@gmail.com</a>.</p>
<h2 id="heading-note">Note</h2>
<p>This book is provided for free on freeCodeCamp as described above and according to <a target="_blank" href="https://creativecommons.org/licenses/by-nc-sa/4.0/deed.en">Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International</a>.</p>
<p>If you would like to support this book, you are welcome to buy the <a target="_blank" href="https://www.amazon.com/dp/B0CQXTJ5V5">Paperback version</a>, an <a target="_blank" href="https://www.buymeacoffee.com/omerr/e/197232">E-Book version</a>, or <a target="_blank" href="https://www.buymeacoffee.com/omerr">buy me a coffee</a>. Thank you!</p>
<h1 id="heading-part-1-main-objects-and-introducing-changes">Part 1 - Main Objects and Introducing Changes</h1>
<h2 id="heading-chapter-1-git-objects">Chapter 1 - Git Objects</h2>
<p>It's time to start your journey into the depths of Git. In this chapter - starting with the basics - you will learn about the most important Git objects, and adopt a way of thinking about Git. Let's get to it!</p>
<h3 id="heading-git-as-a-system-for-maintaining-a-file-system">Git as a System for Maintaining a File System</h3>
<p>While there are different ways to use Git, I'll adopt here the way I've found to be the most clear and useful: Viewing Git as a system maintaining a file system, and specifically  -  snapshots of that file system over time.</p>
<p>A file system begins with a root directory (in UNIX-based systems, <code>/</code>), which usually contains other directories (for example, <code>/usr</code> or <code>/bin</code>). These directories contain other directories, and/or files (for example, <code>/usr/1.txt</code>). On a Windows machine, a root directory of a drive would be <code>C:\</code>, and a subdirectory could be <code>C:\users</code>. I will adopt the convention of UNIX-based systems throughout this book.</p>
<h3 id="heading-blobs">Blobs</h3>
<p>In Git, the contents of files are stored in objects called <strong>blob</strong>s, short for binary large objects.</p>
<p>The difference between blobs and files is that files also contain meta-data. For example, a file "remembers" when it was created, so if you move that file from one directory into another directory, its creation time remains the same.</p>
<p>Blobs, in contrast, are just binary streams of data, like a file's contents. A blob does not register its creation date, its name, or anything other than its contents.</p>
<p>Every blob in Git is identified by its <a target="_blank" href="https://en.wikipedia.org/wiki/SHA-1">SHA-1 hash</a>. SHA-1 hashes consist of 20 bytes, usually represented by 40 characters in hexadecimal form. Throughout this book I will sometimes show just the first characters of that hash. As hashes, and specifically SHA-1 hashes are so ubiquitous within Git, it is important you understand the basic characteristics of hashes.</p>
<h3 id="heading-hashes">Hashes</h3>
<p>A hash is a deterministic, one-way mathematical function.</p>
<p><em>Deterministic</em> means that the same input will provide the same output. That is - you take a stream of data, run a hash function on that stream, and you get a result. </p>
<p>For example, if you provide the SHA-1 hash function with the stream <code>hello</code>, you will get <code>0xaaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d</code>. If you run the SHA-1 hash function again, from a different machine, and provide it the same data (<code>hello</code>), you will get the same value.</p>
<p>Git uses SHA-1 as its hash function in order to identify objects. It relies on it being deterministic, such that an object will always have the same identifier.</p>
<p>A <em>one-way</em> function is a function that is hard to invert given an output. That is,  it is impossible (or at least, very hard) to tell, given the result of the hash function (for example <code>0xaaf4c61ddcc5e8a2dabede0f3b482cd9aea9434d</code>), what input yielded that result (in this example, <code>hello</code>).</p>
<h3 id="heading-back-to-git">Back to Git</h3>
<p>Back to Git - Blobs, just like other Git objects, have SHA-1 hashes associated with them.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/blob_sha.png" alt="Blobs have corresponding SHA-1 values" width="600" height="400" loading="lazy">
<em>Blobs have corresponding SHA-1 values</em></p>
<p>As I said in the beginning, Git can be viewed as a system to maintain a file system. File systems consist of files and directories. A blob is the Git object representing the contents of a file.</p>
<h3 id="heading-trees">Trees</h3>
<p>In Git, the equivalent of a directory is a <strong>tree</strong>. A tree is basically a directory listing, referring to blobs, as well as other trees.</p>
<p>Trees are identified by their SHA-1 hashes as well. Referring to these objects, either blobs or other trees, happens via the SHA-1 hash of the objects.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/tree_objs.png" alt="A tree is a directory listing" width="600" height="400" loading="lazy">
<em>A tree is a directory listing</em></p>
<p>Consider the drawing above. Note that the tree <code>CAFE7</code> refers to the blob <code>F92A0</code> as the file <code>pic.png</code>. In another tree, that same blob may have another name - but as long as the contents are the same, it will still be the same blob object, and still have the same SHA-1 value.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/tree_sub_trees.png" alt="A tree may contain sub-trees, as well as blobs" width="600" height="400" loading="lazy">
<em>A tree may contain sub-trees, as well as blobs</em></p>
<p>The diagram above is equivalent to a file system with a root directory that has one file at <code>/test.js</code>, and a directory named <code>/docs</code> consisting of two files: <code>/docs/pic.png</code>, and <code>/docs/1.txt</code>.</p>
<h3 id="heading-commits">Commits</h3>
<p>Now it's time to take a snapshot of that file system — and store all the files that existed at that time, along with their contents.</p>
<p>In Git, a snapshot is a <strong>commit</strong>. A commit object includes a pointer to the main tree (the root directory of the file system), as well as other meta-data such as the committer (the user who authored the commit), a commit message, and the commit time.</p>
<p>In most cases, a commit also has one or more parent commits — the previous snapshot (or snapshots). Of course, commit objects are also identified by their SHA-1 hashes. These are the hashes you are probably used to seeing when you use commands such as <code>git log</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit.png" alt="A commit is a snapshot in time. It refers to the root tree. As this is the first commit, it has no parents" width="600" height="400" loading="lazy">
<em>A commit is a snapshot in time. It refers to the root tree. As this is the first commit, it has no parents</em></p>
<p>Every commit holds the entire snapshot, not just differences between itself and its parent commit or commits.</p>
<p>How can that work? Doesn't that mean that Git has to store a lot of data for every commit?</p>
<p>Examine what happens if you change the contents of a file. Say that you edit the file <code>1.txt</code>, and add an exclamation mark — that is, you changed the content from <code>HELLO WORLD</code>, to <code>HELLO WORLD!</code>.</p>
<p>Well, this change means that Git creates a new blob object, with a new SHA-1 hash. This makes sense, as <code>sha1("HELLO WORLD")</code> is different from <code>sha1("HELLO WORLD!")</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_blob_new_sha.png" alt="Changing the blob results in a new SHA-1" width="600" height="400" loading="lazy">
<em>Changing the blob results in a new SHA-1</em></p>
<p>Since you have a new hash, then the tree's listing should also change. After all, your tree no longer points to blob <code>73D8A</code>, but rather blob <code>62E7A</code> instead. Since you change the tree's contents, you also change its hash.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_tree_new_hash.png" alt="The tree that points to the changed blob needs to change as well" width="600" height="400" loading="lazy">
<em>The tree that points to the changed blob needs to change as well</em></p>
<p>And now, since the hash of that tree is different, you also need to change the parent tree — as the latter no longer points to tree <code>CAFE7</code>, but rather to tree <code>24601</code>. Consequently, the parent tree will also have a new hash.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_root_tree.png" alt="The root tree also changes, and so does its hash" width="600" height="400" loading="lazy">
<em>The root tree also changes, and so does its hash</em></p>
<p>Almost ready to create a new commit object, and it seems like you are going to store a lot of data — the entire file system, once more! But is that really necessary?</p>
<p>Actually, some objects, specifically blob objects, haven't changed since the previous commit — the blob <code>F92A0</code> remained intact, and so did the blob <code>F00D1</code>.</p>
<p>So this is the trick — as long as an object doesn't change, Git doesn't store it again. In this case, Git doesn't need to store blob <code>F92A0</code> or blob <code>F00D1</code> once more. Git can refer to them using only their hash values. You can then create your commit object.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_commit.png" alt="Blobs that remained intact are referenced by their hash values" width="600" height="400" loading="lazy">
<em>Blobs that remained intact are referenced by their hash values</em></p>
<p>Since this commit is not the first commit, it also has a parent commit — commit <code>A1337</code>.</p>
<h3 id="heading-considering-hashes">Considering Hashes</h3>
<p>After introducing blobs, trees, and commits - consider the hashes of these objects. Assume I wrote the string <code>Git is awesome!</code>, and created a blob object from it. You did the same on your system. Would we have the same hash?</p>
<p>The answer is — Yes. Since the blobs consist of the same data, they'll have the same SHA-1 values.</p>
<p>What if I made a tree that references the blob of <code>Git is awesome!</code>, and gave it a specific name and metadata, and you did exactly the same on your system. Would we have the same hash?</p>
<p>Again, yes. Since the tree objects are the same, they would have the same hash.</p>
<p>What if I created a commit pointing to that tree with the commit message <code>Hello</code>, and you did the same on your system? Would we have the same hash?</p>
<p>In this case, the answer is — No. Even though our commit objects refer to the same tree, they have different commit details — time, committer, and so on.</p>
<h3 id="heading-how-are-objects-stored">How Are Objects Stored?</h3>
<p>You now understand the purpose of blobs, trees, and commits. In the next chapters, you will also create these objects yourself. Despite being interesting, understanding how these objects are actually encoded and stored is not vital to your understanding, and for gitting things done.</p>
<h4 id="heading-short-recap-git-objects">Short Recap - Git Objects</h4>
<p>To recap, in this section we introduced three Git objects:</p>
<ul>
<li><strong>Blob</strong> — contents of a file.</li>
<li><strong>Tree</strong> — a directory listing (of blobs and trees).</li>
<li><strong>Commit</strong> — a snapshot of the working tree.</li>
</ul>
<p>In the next chapter, we will understand branches in Git.</p>
<h2 id="heading-chapter-2-branches-in-git">Chapter 2 - Branches in Git</h2>
<p>In the previous chapter, I suggested that we should view Git as a system for maintaining a file system.</p>
<p>One of the wonders of Git is that it enables multiple people to work on that file system, in parallel, (mostly) without interfering with each other's work. Most people would say that they are "working on branch <code>X</code>." But what does that <em>actually</em> mean?</p>
<p><strong>A branch is just a named reference to a commit.</strong></p>
<p>You can always reference a commit by its SHA-1 hash, but humans usually prefer other ways to name objects. A branch is one way to reference a commit, but it's really just that.</p>
<p>In most repositories, the main line of development is done in a branch called <code>main</code>. This is just a name, and it's created when you use <code>git init</code>, making it widely used. However, you could use any other name you'd like.</p>
<p>Typically, the branch points to the latest commit in the line of development you are currently working on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/branch_01.png" alt="A branch is just a named reference to a commit" width="600" height="400" loading="lazy">
<em>A branch is just a named reference to a commit</em></p>
<p>To create another branch, you can use the <code>git branch</code> command. When you do that, Git creates another pointer. If you created a branch called <code>test</code>, by using <code>git branch test</code>, you would be creating another pointer that points to the same commit as the branch you are on:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_branch.png" alt="Using  creates another pointer" width="600" height="400" loading="lazy">
<em>Using <code>git branch</code> creates another pointer</em></p>
<p>How does Git know which branch you're currently on? It keeps another designated pointer, called <code>HEAD</code>. Usually, <code>HEAD</code> points to a branch, which in turns points to a commit. In the case described, <code>HEAD</code> might point to <code>main</code>, which in turn points to commit <code>B2424</code>. In some cases, <code>HEAD</code> can also point to a commit directly.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/head_main.png" alt=" points to the branch you are currently on" width="600" height="400" loading="lazy">
<em><code>HEAD</code> points to the branch you are currently on</em></p>
<p>To switch the active branch to be <code>test</code>, you can use the command <code>git checkout test</code>, or <code>git switch test</code>. Now you can already guess what this command actually does — it just changes <code>HEAD</code> to point to <code>test</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/head_test.png" alt=" changes where  points" width="600" height="400" loading="lazy">
<em><code>git checkout test</code> changes where <code>HEAD</code> points</em></p>
<p>You could also use <code>git checkout -b test</code> before creating the <code>test</code> branch, which is the equivalent of running <code>git branch test</code> to create the branch, and then <code>git checkout test</code> to move <code>HEAD</code> to point to the new branch.</p>
<p>At the point represented in the drawing above, what would happen if you made some changes and created a new commit using <code>git commit</code>? Which branch will the new commit be added to?</p>
<p>The answer is the <code>test</code> branch, as this is the active branch (since <code>HEAD</code> points to it). Afterwards, the <code>test</code> pointer will move to the newly added commit. Note that <code>HEAD</code> still points to <code>test</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/test_commit-1.png" alt="Every time we use , the branch pointer moves to the newly created commit" width="600" height="400" loading="lazy">
<em>Every time we use <code>git commit</code>, the branch pointer moves to the newly created commit</em></p>
<p>If you go back to <code>main</code> by using <code>git checkout main</code>, Git will move <code>HEAD</code> to point to <code>main</code> again.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/back_to_main-1.png" alt="The resulting state after using " width="600" height="400" loading="lazy">
<em>The resulting state after using <code>git checkout main</code></em></p>
<p>Now, if you create another commit, which branch will it be added to?</p>
<p>That's right, it will be added to the <code>main</code> branch (and its parent would be commit <code>B2424</code>).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_to_main-1.png" alt="The resulting state after creating another commit on the  branch" width="600" height="400" loading="lazy">
<em>The resulting state after creating another commit on the <code>main</code> branch</em></p>
<h3 id="heading-short-recap-branches">Short Recap - Branches</h3>
<ul>
<li>A branch is a named reference to a commit.</li>
<li>When you use <code>git commit</code>, Git creates a commit object, and moves the branch to point to the newly created commit.</li>
<li><code>HEAD</code> is a special pointer telling Git which branch is the active branch (in rare cases, it can point directly to a commit).</li>
</ul>
<p>In the next chapters, you will learn how to introduce changes to Git. You will create a repository from scratch — without using <code>git init</code>, <code>git add</code>, or <code>git commit</code>. This will allow you to deepen your understanding of what is happening under the hood when you work with Git. You will also create new branches, switch branches, and create additional commits — all without using <code>git branch</code> or <code>git checkout</code>. I don't know about you, but I am excited already!</p>
<h2 id="heading-chapter-3-how-to-record-changes-in-git">Chapter 3 - How to Record Changes in Git</h2>
<p>So far, we've learned about four different entities in Git:</p>
<ol>
<li><strong>Blob</strong> — contents of a file.</li>
<li><strong>Tree</strong> — a directory listing (of blobs and trees).</li>
<li><strong>Commit</strong> — a snapshot of the working tree, with some meta-data such as the time or the commit message.</li>
<li><strong>Branch</strong> — a named reference to a commit.</li>
</ol>
<p>The first three are <em>objects</em>, whereas the fourth is one way to refer to objects (specifically, commits).</p>
<p>Now, it's time to understand how to introduce changes in Git.</p>
<p>When you work on your source code, you work from a <strong>working dir</strong>. A working dir(ectory) (also called "working tree") is any directory on your file system which has a repository associated with it. It contains the folders and files of your project, and also a directory called <code>.git</code> that we will talk more about later. Remember that we said that Git is a system to maintain a file system. The working directory is the root of the file system for Git.</p>
<p>After you make some changes, you might want to record them in your repository. A <strong>repository</strong> (in short: "repo") is a collection of commits, each of which is an archive of what the project's working tree looked like at a past date, whether on your machine or someone else's. That is, as I said before, a commit is a snapshot of the working tree.</p>
<p>A repository also includes things other than your code files, such as <code>HEAD</code> and <code>branches</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/working_dir_repo.png" alt="A working dir alongside the repository" width="600" height="400" loading="lazy">
<em>A working dir alongside the repository</em></p>
<p>Note regarding the drawing conventions I use: I include <code>.git</code> within the working directory, to remind you that it is a folder within the project's folder on the filesystem. The <code>.git</code> folder actually contains the objects of the repository, as we will see in <a class="post-section-overview" href="#heading-chapter-4-how-to-create-a-repo-from-scratch">chapter 4</a>.</p>
<p>There are other version control systems where changes are committed directly from the working dir to the repository. In Git, this is not the case. Instead, changes are first registered in something called the <strong>index</strong>, or the <strong>staging area</strong>.</p>
<p>Both of these terms refer to the same thing, and they are used often in Git's documentation. I will use these terms interchangeably throughout this book, as you should feel comfortable with both of them.</p>
<p>You can think of adding changes to the index as a way of "confirming" your changes, one by one, before creating a commit (which records all your approved changes at once).</p>
<p>When you <code>checkout</code> a branch, Git populates the index and the working dir with the contents of the files as they exist in the commit that branch is pointing to. When you use <code>git commit</code>, Git creates a new commit object based on the state of the index.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/working_dir_index_repo.png" alt="The three &quot;states&quot; - working dir, index, and repository" width="600" height="400" loading="lazy">
<em>The three "states" - working dir, index, and repository</em></p>
<p>Using the index allows you to carefully prepare each commit. For example, you may have two files with changes in your working dir:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/working_dir_index_repo_02.png" alt="Working dir includes two files with changes" width="600" height="400" loading="lazy">
<em>Working dir includes two files with changes</em></p>
<p>For example, assume these two files are <code>1.txt</code> and <code>2.txt</code>. It is possible to only add one of them (for instance, <code>1.txt</code>) to the index, by using <code>git add 1.txt</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/working_dir_index_repo_03.png" alt="The state after staging " width="600" height="400" loading="lazy">
<em>The state after staging <code>1.txt</code></em></p>
<p>As a result, the state of the index matches the state of <code>HEAD</code> (in this case, "Commit 2"), with the exception of the file <code>1.txt</code>, which matches the state of <code>1.txt</code> in the working directory. Since you did not stage <code>2.txt</code>, the index does not include the updated version of <code>2.txt</code>. So the state of <code>2.txt</code> in the index matches the state of <code>2.txt</code> in "Commit 2".</p>
<p>Behind the scenes - once you stage a version of a file, Git creates a blob object with the file's contents. This blob object is then added to the index. As long as you only modify the file on the working directory, without staging it, the changes you make are not recorded in blob objects. </p>
<p>When considering the previous figure, note that I do not draw the staged version of the file as part of the "repository", as in this representation, the "repository" refers to a tree of commits and their references, and this blob has not been a part of any commit.</p>
<p>Now, you can use <code>git commit</code> to record the change to <code>1.txt</code> <em>only</em>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/working_dir_index_repo_04.png" alt="The state after using " width="600" height="400" loading="lazy">
<em>The state after using <code>git commit</code></em></p>
<p>Using <code>git commit</code> performs two main operations:</p>
<ol>
<li>It creates a new commit object. This commit object reflects the state of the index when you ran the <code>git commit</code> command.</li>
<li>Updates the active branch to point to the newly created commit. In this example, <code>main</code> now points to "Commit 3", the new commit object.</li>
</ol>
<h3 id="heading-how-to-create-a-repo-the-conventional-way">How to Create a Repo — The Conventional Way</h3>
<p>Let's make sure that you understand how the terms we've introduced relate to the process of creating a new repository. This is a quick high-level view, before diving much deeper into this process.</p>
<p>Initialize a new repository using <code>git init my_repo</code>, and then change your directory to that of the repository using <code>cd my_repo</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_init.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git init</code></em></p>
<p>By using <code>tree -f .git</code> you can see that running <code>git init my_repo</code> resulted in quite a few sub-directories inside <code>.git</code>. (The flag <code>-f</code> includes files in tree's output).</p>
<p>Note: if you're using Windows, run <code>tree /f .git</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_init_tree_f.png" alt="The output of  after using " width="600" height="400" loading="lazy">
<em>The output of <code>tree -f .git</code> after using <code>git init</code></em></p>
<p>Create a file inside the <code>my_repo</code> directory:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_f_txt.png" alt="Creating " width="600" height="400" loading="lazy">
<em>Creating <code>f.txt</code></em></p>
<p>This file is within your working directory. If you run <code>git status</code>, you'll see this file is untracked:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_f_txt_git_status.png" alt="The result of " width="600" height="400" loading="lazy">
<em>The result of <code>git status</code></em></p>
<p>Files in your working directory can be in one of two states: <strong>tracked</strong> or <strong>untracked</strong>.</p>
<p><strong>Tracked</strong> files are files that Git "knows" about. They either were in the last commit, or they are staged now (that is, they are in the staging area).</p>
<p><strong>Untracked</strong> files are everything else — any files in your working directory that were not in your last commit, and are not in your staging area.</p>
<p>The new file (<code>f.txt</code>) is currently untracked, as you haven't added it to the staging area, and it hasn't been included in a previous commit.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/drawing_new_untracked_file.png" alt=" is in the working directory (and untracked)" width="600" height="400" loading="lazy">
<em><code>f.txt</code> is in the working directory (and untracked)</em></p>
<p>You can now add this file to the staging area (also referred to as staging this file) by using <code>git add f.txt</code>. You can verify that it has been staged by running <code>git status</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_add_status.png" alt="Adding the new file to the staging area" width="600" height="400" loading="lazy">
<em>Adding the new file to the staging area</em></p>
<p>So now the state of the index matches that of the working dir:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/drawing_new_staged_file.png" alt="The state after adding the new file" width="600" height="400" loading="lazy">
<em>The state after adding the new file</em></p>
<p>You can now create a commit using <code>git commit</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/initial_commit.png" alt="Committing an initial commit" width="600" height="400" loading="lazy">
<em>Committing an initial commit</em></p>
<p>If you run <code>git status</code> again, you'll see that the status is clean - that is, the state of <code>HEAD</code> (which points to your initial commit) equals the state of the index, and also the state of the working dir. By using <code>git log</code> you will see indeed that <code>HEAD</code> points to <code>main</code> which in turn points to your new commit:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/initial_commit_git_log.png" alt="The output of  after introducing the first commit" width="600" height="400" loading="lazy">
<em>The output of <code>git log</code> after introducing the first commit</em></p>
<p>Has something changed within the <code>.git</code> directory? Run <code>tree -f .git</code> to check:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/tree_f_after_initial_commit.png" alt="A lot of things have changed within " width="600" height="400" loading="lazy">
<em>A lot of things have changed within <code>.git</code></em></p>
<p>Apparently, quite a lot has changed. It's time to dive deeper into the structure of <code>.git</code> and understand what is going on under the hood when you run <code>git init</code>, <code>git add</code> or <code>git commit</code>. That's exactly what the next chapter will cover.</p>
<h3 id="heading-recap-how-to-record-changes-in-git">Recap - How to Record Changes in Git</h3>
<p>You learned about the three different "states" of the file system that Git maintains:</p>
<ul>
<li><strong>Working dir(ectory)</strong> (also called "working tree") - any directory on your file system which has a repository associated with it.</li>
<li><strong>Index</strong>, or the <strong>Staging Area</strong> - a playground for the next commit.</li>
<li><strong>Repository</strong> (in short: "repo") - a collection of commits, each of which is a snapshot of the working tree.</li>
</ul>
<p>When you introduce changes in Git, you almost always follow this order:</p>
<ol>
<li>You change the working directory first</li>
<li>Then you stage these changes (or some of them) to the index</li>
<li>And finally, you commit these changes - thereby updating the repository with a new commit. The state of this new commit matches the state of the index.</li>
</ol>
<p>Ready to dive deeper?</p>
<h2 id="heading-chapter-4-how-to-create-a-repo-from-scratch">Chapter 4 - How to Create a Repo From Scratch</h2>
<p>So far we've covered some Git fundamentals, and now you should be ready to really <em>Git</em> going (I can't seem to get enough of that pun).</p>
<p>In order to deeply understand how Git works, you will create a repository, but this time — you will build it from scratch. As in other chapters, I encourage you to try out the commands alongside this chapter.</p>
<h3 id="heading-how-to-set-up-git">How to Set Up <code>.git</code></h3>
<p>Create a new directory, and run <code>git status</code> within it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_dir_git_status.png" alt=" in a new directory" width="600" height="400" loading="lazy">
<em><code>git status</code> in a new directory</em></p>
<p>Alright, so Git seems unhappy as you don't yet have a <code>.git</code> folder. The natural thing to do would be to create that directory and try again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/mkdir_git_git_status.png" alt=" after creating " width="600" height="400" loading="lazy">
<em><code>git status</code> after creating <code>.git</code></em></p>
<p>Apparently, creating a <code>.git</code> directory is just not enough. You need to add some content to that directory.</p>
<p>A Git repository has two main components:</p>
<ul>
<li>A collection of <strong>objects</strong> — blobs, trees, and commits.</li>
<li>A system of <strong>naming</strong> those objects — called references.</li>
</ul>
<p>A repository may also contain other things, such as hooks, but at the very least — it must include objects and references.</p>
<p>Create a directory for the objects at <code>.git/objects</code>, and a directory for the references (in short: "refs") at <code>.git/refs</code> (on Windows systems — <code>.git\   objects</code> and <code>.git\refs</code>, respectively).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_folders_git_tree.png" alt="Considering the directory tree" width="600" height="400" loading="lazy">
<em>Considering the directory tree</em></p>
<p>One type of reference is branches. Internally, Git calls branches by the name <code>heads</code>. Create a directory for branches — <code>.git/refs/heads</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_heads_folder_git_tree.png" alt="The directory tree" width="600" height="400" loading="lazy">
<em>The directory tree</em></p>
<p>This still doesn't change the result of <code>git status</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_heads_folder_git_status.png" alt=" after creating " width="600" height="400" loading="lazy">
<em><code>git status</code> after creating <code>.git/refs/heads</code></em></p>
<p>How does Git know where to start when looking for a commit in the repository? As I explained earlier, it looks for <code>HEAD</code>, which points to the current active branch (or commit, in some cases).</p>
<p>So, you need to create <code>HEAD</code>, which is just a file residing at <code>.git/HEAD</code>. You can apply the following:</p>
<p>On UNIX:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"ref: refs/heads/main"</span> &gt; .git/HEAD
</code></pre>
<p>On Windows:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> ref: refs/heads/main &gt; .git\HEAD
</code></pre>
<p>So you now know how <code>HEAD</code> is implemented — it is simply a file, and its contents describe what it points to.</p>
<p>Following the command above, <code>git status</code> seems to change its mind:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_head_git_status.png" alt=" is just a file" width="600" height="400" loading="lazy">
<em><code>HEAD</code> is just a file</em></p>
<p>Notice that Git "believes" you are on a branch called <code>main</code>, even though you haven't created this branch. <code>main</code> is just a name. You can also make Git believe you are on a branch called <code>banana</code> if you wish:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/banana.png" alt="Creating a branch named " width="600" height="400" loading="lazy">
<em>Creating a branch named <code>banana</code></em></p>
<p>Switch back to <code>main</code>, as you will keep working from (mostly) there throughout this chapter, just to adhere to the regular convention:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"ref: refs/heads/main"</span> &gt; .git/HEAD
</code></pre>
<p>Now that you have your <code>.git</code> directory ready, you can work your way to make a commit (again, without using <code>git add</code> or <code>git commit</code>).</p>
<h3 id="heading-plumbing-vs-porcelain-commands-in-git">Plumbing vs Porcelain Commands in Git</h3>
<p>At this point, it would be helpful to make a distinction between two types of Git commands: plumbing and porcelain. The application of the terms oddly comes from toilets, traditionally made of porcelain, and the infrastructure of plumbing (pipes and drains).</p>
<p>The porcelain layer provides a user-friendly interface to the plumbing. Most people only deal with the porcelain. Yet, when things go (terribly) wrong, and someone wants to understand why, they would have to roll up their sleeves and deal with the plumbing.</p>
<p>Git uses this terminology as an analogy to separate the low-level commands that users don't usually need to use directly ("plumbing" commands) from the more user-friendly high level commands ("porcelain" commands).</p>
<p>So far, you have dealt with porcelain commands — <code>git init</code>, <code>git add</code> or <code>git commit</code>. It's time to go deeper, and get yourself acquainted with some plumbing commands.</p>
<h3 id="heading-how-to-create-objects-in-git">How to Create Objects in Git</h3>
<p>Start by creating an object and writing it into the objects database of Git, residing within <code>.git/objects</code>. To know the SHA-1 hash value of a blob, you can <code>git hash-object</code> (yes, a plumbing command), in the following way:</p>
<p>On UNIX:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"Git is awesome"</span> | git hash-object --stdin
</code></pre>
<p>On Windows:</p>
<pre><code class="lang-bash">&gt; <span class="hljs-built_in">echo</span> Git is awesome | git hash-object --stdin
</code></pre>
<p>By using <code>--stdin</code> you are instructing <code>git hash-object</code> to take its input from the standard input. This will provide you with the relevant hash value:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/hash_object.png" alt="Getting a blob's SHA-1" width="600" height="400" loading="lazy">
<em>Getting a blob's SHA-1</em></p>
<p>In order to actually write that blob into Git's object database, you can add the <code>-w</code> switch for <code>git hash-object</code>. Then, you check the contents of the <code>.git</code> folder, and see that they have changed:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/write_blob.png" alt="Writing a blob to the objects' database" width="600" height="400" loading="lazy">
<em>Writing a blob to the objects' database</em></p>
<p>You can see that the hash of your blob is <code>7a9bd34a0244eaf2e0dda907a521f43d417d94f6</code>. You can also see that a directory has been created under <code>.git/objects</code>, a directory named <code>7a</code>, and within it, a file by the name of <code>9bd34a0244eaf2e0dda907a521f43d417d94f6</code>.</p>
<p>What Git did here is take the <em>first two characters</em> of the SHA-1 hash, and use them as the name of a directory. The remaining characters are used as the filename for the file that actually contains the blob.</p>
<p>Why is that so? Consider a fairly big repository, one that has 400,000 objects (blobs, trees, and commits) in its database. Looking up a hash inside that list of 400,000 hashes might take a while. Thus, Git simply divides that problem by <code>256</code>. </p>
<p>To look up the hash above, Git would first look for the directory named <code>7a</code> inside the directory <code>.git/objects</code>, which may have up to 256 directories (<code>00</code> through <code>FF</code>). Then, it will search within that directory, narrowing down the search as it goes.</p>
<p>Back to the process of generating a commit. You have just created an object. What is the type of that object? You can use another plumbing command, <code>git cat-file -t</code> (<code>-t</code> stands for "type"), to check that out:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cat_file_t_blob.png" alt="Using  reveals the type of the Git object" width="600" height="400" loading="lazy">
_Using <code>git cat-file -t &amp;lt;object_sha&amp;gt;</code> reveals the type of the Git object_</p>
<p>Not surprisingly, this object is a blob. You can also use <code>git cat-file -p</code> (<code>-p</code> stands for "pretty-print") to see its contents:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cat_file_p_blob.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git cat-file -p</code></em></p>
<p>This process of creating a blob object under <code>.git/objects</code> usually happens when you add something to the staging area — that is, when you use <code>git add</code>. So blobs are not created every time you save a file to the file system (the working dir), but only when you stage it.</p>
<p>Remember that Git creates a blob of the <em>entire</em> file that is staged. Even if a single character is modified or added, the file has a new blob with a new hash (as in the example in <a class="post-section-overview" href="#heading-chapter-1-git-objects">chapter 1</a> where you added <code>!</code> at the end of a line).</p>
<p>Will there be any change to <code>git status</code>?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_after_blob.png" alt=" after creating a blob object" width="600" height="400" loading="lazy">
<em><code>git status</code> after creating a blob object</em></p>
<p>Apparently, no. Adding a blob object to Git's internal database does not change the status, as Git does not know of any tracked (or untracked) files at this stage.</p>
<p>You need to track this file — add it to the staging area. To do that, you can use another plumbing command, <code>git update-index</code>, like so:</p>
<pre><code class="lang-bash">git update-index --add --cacheinfo 100644 &lt;blob-hash&gt; &lt;filename&gt;
</code></pre>
<p>Note: The <code>cacheinfo</code> is a 16-bit file mode as stored by Git, following the layout of POSIX types and modes. This is not within the scope of this book, as it is really not important for you to Git things done.</p>
<p>Running the command above will result in a change to <code>.git</code>'s contents:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/update_index.png" alt="The state of  after updating the index" width="600" height="400" loading="lazy">
<em>The state of <code>.git</code> after updating the index</em></p>
<p>Can you spot the change? A new file by the name of <code>index</code> has been created. This is it — the famous index (or staging area), is basically a file that resides within <code>.git/index</code>.</p>
<p>So now that your blob has been added to the index, do you expect <code>git status</code> to look different?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_after_update_index.png" alt=" after using " width="600" height="400" loading="lazy">
<em><code>git status</code> after using <code>git update-index</code></em></p>
<p>That's interesting! Two things happened here.</p>
<p>First, you can see that <code>awesome.txt</code> appears in <em>green</em>, in the "Changes to be committed" area. That is so because the index now includes <code>awesome.txt</code>, waiting to be committed.</p>
<p>Second, we can see that <code>awesome.txt</code> appears in <em>red</em> — because Git believes the file <code>awesome.txt</code> has been deleted, and the fact that the file has been deleted is not staged.</p>
<p>(Note: You may have noticed that I sometimes refer to Git with words such as "believes", "thinks", or "wants". As I explained in the <a class="post-section-overview" href="#heading-introduction">introduction of this book</a> - in order for us to enjoy playing around with Git, and reading (and writing) this book, I feel like referring to Git as more than just code makes it all so much more enjoyable.)</p>
<p>This happens as you added the blob with the contents <code>Git is awesome</code> to the objects' database, and updated the index that the file <code>awesome.txt</code> holds the contents of that blob, but you never actually created that file on disk.</p>
<p>You can easily solve this by taking the contents of the blob and writing them to our file system, to a file called <code>awesome.txt</code>:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> <span class="hljs-string">"Git is awesome"</span> &gt; awesome.txt
</code></pre>
<p>As a result, it will no longer appear in red by <code>git status</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_after_creating_file_on_disk.png" alt=" after creating  on disk" width="600" height="400" loading="lazy">
<em><code>git status</code> after creating <code>awesome.txt</code> on disk</em></p>
<p>So now it's time to create a commit object from your staging area. As explained in <a class="post-section-overview" href="#heading-chapter-1-git-objects">chapter 1</a>, a commit object has a reference to a tree, so you need to create a tree.</p>
<p>You can achieve this using the command <code>git write-tree</code>, which records the contents of the index in a tree object. Of course, you can use git <code>cat-file -t</code> to see that it's indeed a tree:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/write_tree.png" alt="Creating a tree object with the contents of the index" width="600" height="400" loading="lazy">
<em>Creating a tree object with the contents of the index</em></p>
<p>And you can use <code>git cat-file -p</code> to see its contents:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cat_file_p_tree.png" alt=" to see the tree's contents" width="600" height="400" loading="lazy">
<em><code>git cat-file -p</code> to see the tree's contents</em></p>
<p>Great, so you created a tree, and now you need to create a commit object that references this tree. To do that, you can use the command:</p>
<pre><code class="lang-bash">git commit-tree &lt;tree-hash&gt; -m &lt;commit message&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit-tree.png" alt="Committing using the tree object" width="600" height="400" loading="lazy">
<em>Committing using the tree object</em></p>
<p>You should now feel comfortable with the commands used to check the created object's type, and print its contents:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_object_cat_file.png" alt="Creating a commit object" width="600" height="400" loading="lazy">
<em>Creating a commit object</em></p>
<p>Note that this commit object doesn't have a parent, because it is the first commit. When you add another commit you will probably want to declare its parent — don't worry, you will do so later.</p>
<p>The last hash that we got — <code>b6d05ee40344ef5d53502539772086da14ad2b07</code> – is a commit's hash. You should actually be used to using these hashes — you probably look at them all the time (when using <code>git log</code>, for instance). Note that this commit object points to a tree object, with its own hash, which you rarely specify explicitly.</p>
<p>Will something change in <code>git status</code>?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_after_creating_commit_object.png" alt=" after creating a commit object" width="600" height="400" loading="lazy">
<em><code>git status</code> after creating a commit object</em></p>
<p>No, nothing has changed. Why is that?</p>
<p>Well, to know that your file has been committed, Git needs to know about the latest commit. How does Git do that? It goes to the <code>HEAD</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/looking_at_head_1.png" alt="Looking at the contents of " width="600" height="400" loading="lazy">
<em>Looking at the contents of <code>HEAD</code></em></p>
<p><code>HEAD</code> points to <code>main</code>, but what is <code>main</code>? You haven't really created it yet.</p>
<p>As we explained earlier in <a class="post-section-overview" href="#heading-chapter-2-branches-in-git">chapter 2</a>, a branch is simply a named reference to a commit. And in this case, we would like <code>main</code> to refer to the commit object with the hash <code>b6d05ee40344ef5d53502539772086da14ad2b07</code>.</p>
<p>You can achieve this by creating a file at <code>.git/refs/heads/main</code>, with the contents of this hash, like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/creating_main.png" alt="Creating " width="600" height="400" loading="lazy">
<em>Creating <code>main</code></em></p>
<p>In sum, a branch is just a file inside <code>.git/refs/heads</code>, containing a hash of the commit it refers to.</p>
<p>Now, finally, <code>git status</code> and <code>git log</code> seem to appreciate our efforts:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_commit_1.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git status</code></em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_commit_1.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git log</code></em></p>
<p>You have successfully created a commit without using porcelain commands! How cool is that?</p>
<h3 id="heading-recap-how-to-create-a-repo-from-scratch">Recap - How to Create a Repo From Scratch</h3>
<p>In this chapter, you fearlessly deep-dived into Git. You stopped using porcelain commands and switched to plumbing commands.</p>
<p>By using echo and low-level commands such as <code>git hash-object</code>, you were able to create a blob, add it to the index, create a tree of the index, and create a commit object pointing to that tree.</p>
<p>You also learned that <code>HEAD</code> is a file, located in <code>.git/HEAD</code>. Branches are also files, located under <code>.git/refs/heads</code>. When you understand how Git operates, those abstract notions of <code>HEAD</code> or "branches" become very tangible.</p>
<p>The next chapter will deepen your understanding of how branches work under the hood.</p>
<h2 id="heading-chapter-5-how-to-work-with-branches-in-git-under-the-hood">Chapter 5 - How to Work with Branches in Git — Under the Hood</h2>
<p>In the previous chapter you created a repository and a commit without using <code>git init</code>, <code>git add</code> or <code>git commit</code>. In this chapter, you we will create and switch between branches without using porcelain commands (<code>git branch</code>, <code>git switch</code>, or <code>git checkout</code>).</p>
<p>It's perfectly understandable if you are excited, I am too!</p>
<p>Continuing from the previous chapter - you only have one branch, named <code>main</code>. To create another one with the name <code>test</code> (as the equivalent of <code>git branch test</code>), you would need to create a file named <code>test</code> within <code>.git/refs/heads</code>, and the contents of that file would be the same commit's hash as the <code>main</code> branch points to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_test_branch.png" alt="Creating  branch" width="600" height="400" loading="lazy">
<em>Creating <code>test</code> branch</em></p>
<p>If you use <code>git log</code>, you can see that this is indeed the case — both <code>main</code> and <code>test</code> point to this commit:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_after_creating_test_branch.png" alt=" after creating  branch" width="600" height="400" loading="lazy">
<em><code>git log</code> after creating <code>test</code> branch</em></p>
<p>(Note: if you run this command and don't see a valid output, you may have written something other than the commit's hash into <code>.git/refs/heads/test</code>.)</p>
<p>Next, switch to our newly created branch (the equivalent of <code>git checkout test</code>). How would you do that? Try to answer for yourself before moving on to the next paragraph.</p>
<p>To change the active branch, you should change <code>HEAD</code> to point to your new branch:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/change_head_to_test.png" alt="Switching to branch  by changing " width="600" height="400" loading="lazy">
<em>Switching to branch <code>test</code> by changing <code>HEAD</code></em></p>
<p>As you can see, <code>git status</code> confirms that <code>HEAD</code> now points to <code>test</code>, which is, therefore, the active branch.</p>
<p>You can now use the commands you have already used in the previous chapter to create another file and add it to the index:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/writing_another_file.png" alt="Writing and staging another file" width="600" height="400" loading="lazy">
<em>Writing and staging another file</em></p>
<p>Following the commands above, you:</p>
<ul>
<li>Create a blob with the content of <code>Another File</code> (using <code>git hash-object</code>).</li>
<li>Add it to the index by the name <code>another_file.txt</code> (using <code>git update-index</code>).</li>
<li>Create a corresponding file on disk with the contents of the blob (using <code>git cat-file -p</code>).</li>
<li>Create a tree object representing the index (using <code>git write-tree</code>).</li>
</ul>
<p>It's now time to create a commit referencing this tree. This time, you should also specify the parent of this commit — which would be the previous commit. You specify the parent using the <code>-p</code> switch of <code>git commit-tree</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_2.png" alt="Creating another commit object" width="600" height="400" loading="lazy">
<em>Creating another commit object</em></p>
<p>We have just created a commit, with a tree as well as a parent, as you can see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cat_file_commit_2.png" alt="Observing the new commit object" width="600" height="400" loading="lazy">
<em>Observing the new commit object</em></p>
<p>(Note: the SHA-1 value of your commit object will be different than the one shown in the screenshot above, as it includes the timestamp of the commit, and also author's details - which would be different on your machine.)</p>
<p>Will <code>git log</code> show us the new commit?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_after_creating_commit_2.png" alt=" after creating &quot;Commit 2&quot;" width="600" height="400" loading="lazy">
<em><code>git log</code> after creating "Commit 2"</em></p>
<p>As you can see, <code>git log</code> doesn't show anything new. Why is that?</p>
<p>Remember that <code>git log</code> traces the branches to find relevant commits to show. It shows us now <code>test</code> and the commit it points to, and it also shows <code>main</code> which points to the same commit.</p>
<p>That's right — you need to change <code>test</code> to point to the new commit object. You can do that by changing the contents of <code>.git/refs/heads/test</code>:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> 22267a945af8fde78b62ee7f705bbecfdd276b3d &gt; .git/refs/heads/<span class="hljs-built_in">test</span>
</code></pre>
<p>And now if you run <code>git log</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_after_updating_test_branch.png" alt=" after updating  branch" width="600" height="400" loading="lazy">
<em><code>git log</code> after updating <code>test</code> branch</em></p>
<p>It worked!</p>
<p><code>git log</code> goes to <code>HEAD</code>, which tells Git to go to the branch <code>test</code>, which points to commit <code>222..3d</code>, which links back to its parent commit <code>b6d..07</code>.</p>
<p>Feel free to admire the beauty, I Git you. 😊</p>
<p>By inspecting your repository's folder, you can see that you have six different objects under the folder <code>.git/objects</code> - these are the two blobs you created (one for <code>awesome.txt</code> and one for <code>file.txt</code>), two commit objects ("Commit 1" and "Commit 2"), and the tree objects - each pointed to by one of the commit objects.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/tree_after_commit_2.png" alt="The tree listing after creating &quot;Commit 2&quot;" width="600" height="400" loading="lazy">
<em>The tree listing after creating "Commit 2"</em></p>
<p>You also have <code>.git/HEAD</code> that points to the active branch or commit, and two branches - within <code>.git/refs/heads</code>.</p>
<h3 id="heading-recap-how-to-work-with-branches-in-git-under-the-hood">Recap - How to Work with Branches in Git — Under the Hood</h3>
<p>In this chapter you understood how branches actually work in Git.</p>
<p>The main things we covered:</p>
<ul>
<li>A branch is a file under <code>.git/refs/heads</code>, where the content of the file is a SHA-1 value of a commit.</li>
<li>To create a new branch, Git simply creates a new file under <code>.git/refs/heads</code> with the name of the branch - for example, <code>.git/refs/heads/my_branch</code> for the branch <code>my_branch</code>.</li>
<li>To switch the active branch, Git modifies the contents of <code>.git/HEAD</code> to refer to the new active branch. <code>.git/HEAD</code> may also point to a commit object directly.</li>
<li>When committing using <code>git commit</code>, Git creates a commit object, and also moves the current branch (that is, the contents of the file under <code>.git/refs/heads</code>) to point to the newly created commit object.</li>
</ul>
<h2 id="heading-part-1-summary">Part 1 - Summary</h2>
<p>This part introduced you to the internals of Git. We started by covering <a class="post-section-overview" href="#heading-chapter-1-git-objects">the basic objects</a> — blobs, trees, and commits.</p>
<p>You learned that a <strong>blob</strong> holds the contents of a file. A <strong>tree</strong> is a directory-listing, containing blobs and/or sub-trees. A <strong>commit</strong> is a snapshot of our working directory, with some meta-data such as the time or the commit message.</p>
<p>You learned about <strong><a class="post-section-overview" href="#heading-chapter-2-branches-in-git">branches</a></strong>, seeing that they are nothing but a named reference to a commit.</p>
<p>You learned the process of <a class="post-section-overview" href="#heading-chapter-3-how-to-record-changes-in-git">recording changes in Git</a>, and that it involves the <strong>working directory</strong>, a directory that has a repository associated with it, the <strong>staging area (index)</strong> which holds the tree for the next commit, and the <strong>repository</strong>, which is a collection of commits and references.</p>
<p>We clarified how these terms relate to Git commands we know by creating a new repository and committing a file using the well-known <code>git init</code>, <code>git add</code>, and <code>git commit</code>.</p>
<p>Then you <a class="post-section-overview" href="#heading-chapter-4-how-to-create-a-repo-from-scratch">created a new repository from scratch</a>, by using <code>echo</code> and low-level commands such as <code>git hash-object</code>. You created a blob, added it to the index, created a tree object representing the index, and even created a commit object pointing to that tree.</p>
<p>You were also able to create and <a class="post-section-overview" href="#heading-chapter-5-how-to-work-with-branches-in-git-under-the-hood">switch between branches by modifying files directly</a>. Kudos to those of you who tried this on your own!</p>
<p>All together, after following along through this part, you should feel that you've deepened your understanding of what is happening under the hood when working with Git.</p>
<p>The next part will explore different strategies for integrating changes when working in different branches in Git - specifically, merge and rebase.</p>
<h1 id="heading-part-2-branching-and-integrating-changes">Part 2 - Branching and Integrating Changes</h1>
<h2 id="heading-chapter-6-diffs-and-patches">Chapter 6 - Diffs and Patches</h2>
<p>In Part 1 you learned how Git works under the hood, the different Git objects, and how to create a repo from scratch.</p>
<p>When teams work with Git, they introduce sequences of changes, usually in branches, and then they need to combine different change histories together. To really understand how this is achieved, you should learn how Git treats diffs and patches. You will then apply your knowledge to understand the process of merge and rebase.</p>
<p>Many of the interesting processes in Git like merging, rebasing, or even committing are based on diffs and patches. Developers work with diffs all the time, whether using Git directly or relying on the IDE's diff view. In this chapter, you will learn what Git diffs and patches are, their structure, and how to apply patches.</p>
<p>As a reminder from the <a class="post-section-overview" href="#heading-chapter-1-git-objects">chapter on Git Objects</a>, a commit is a snapshot of the working tree at a certain point in time, in addition to some meta-data.</p>
<p>Yet, it is really hard to make sense of individual commits by looking at the entire working tree. Rather, it is more helpful to look at how different a commit is from its parent commit, that is, the diff between these commits.</p>
<p>So, what do I mean when I say "diff"? Let's start with some history.</p>
<h3 id="heading-git-diffs-history">Git Diff's History</h3>
<p>Git's <code>diff</code> is based on the diff utility on UNIX systems. <code>diff</code> was developed in the early 1970's on the Unix operating system. The first released version shipped with the Fifth Edition of Unix in 1974.</p>
<p><code>git diff</code> is a command that takes two inputs, and computes the difference between them. Inputs can be commits, but also files, and even files that have never been introduced to the repository.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_definition.png" alt="Git diff takes two inputs, which can be commits or files" width="600" height="400" loading="lazy">
<em>Git diff takes two inputs, which can be commits or files</em></p>
<p>This is important - <code>git diff</code> computes the <em>difference</em> between two strings, which most of the time happen to consist of code, but not necessarily.</p>
<h3 id="heading-time-to-get-hands-on">Time to Get Hands-On</h3>
<p>As always, you are encouraged to run the commands yourself while reading this chapter. Unless noted otherwise, I will use the following repository:</p>
<p><a target="_blank" href="https://github.com/Omerr/gitting_things_repo.git">https://github.com/Omerr/gitting_things_repo.git</a></p>
<p>You can clone it locally and have the same starting point I am using for this chapter.</p>
<p>Consider this short text file on my machine, called <code>file.txt</code>, which consists of 6 lines:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/file_txt_1.png" alt=" consists of six lines" width="600" height="400" loading="lazy">
<em><code>file.txt</code> consists of six lines</em></p>
<p>Now, modify this file a bit. Remove the second line, and insert a new line as the fourth line. Add an exclamation mark (<code>!</code>) to the end of the last line, so you get this result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_file_txt_1.png" alt="After modifying , we get different six lines" width="600" height="400" loading="lazy">
<em>After modifying <code>file.txt</code>, we get different six lines</em></p>
<p>Save this file with a new name, <code>new_file.txt</code>.</p>
<p>Now you can run <code>git diff</code> to compute the difference between the files like so:</p>
<pre><code class="lang-bash">git diff --no-index file.txt new_file.txt
</code></pre>
<p>(I will explain the <code>--no-index</code> switch of this command later. For now it's enough to understand it allows us to compare between two files that are not part of a Git repository.)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_1.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git diff --no-index file.txt new_file.txt</code>_</p>
<p>The output of <code>git diff</code> shows quite a lot of things.</p>
<p>Focus on the part starting with <code>This is a file</code>. You can see that the added line (<code>// new test</code>) is preceded by a <code>+</code> sign. The deleted line is preceded by a <code>-</code> sign.</p>
<p>Interestingly, notice that Git views a modified line as a sequence of two changes - erasing a line and adding a new line instead. So the patch includes deleting the last line, and adding a new line that's equal to that line, with the addition of a <code>!</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_format_lines.png" alt="Addition lines are preceded by , deletion lines by , and modification lines are sequences of deletions and additions" width="600" height="400" loading="lazy">
<em>Addition lines are preceded by <code>+</code>, deletion lines by <code>-</code>, and modification lines are sequences of deletions and additions</em></p>
<p>Now would be a good time to discuss the terms "patch" and "diff". These two are often used interchangeably, although there is a distinction, at least historically. </p>
<p>A <strong>diff</strong> shows the differences between two files, or snapshots, and can be quite minimal in doing so. A <strong>patch</strong> is an extension of a diff, augmented with further information such as context lines and filenames, which allow it to be <em>applied</em> more widely. It is a text document that describes how to alter an existing file or codebase.</p>
<p>These days, the Unix <code>diff</code> program, and <code>git diff</code>, can produce patches of various kinds.</p>
<p>A patch is a compact representation of the differences between two files. It describes how to turn one file into another.</p>
<p>In other words, if you apply the "instructions" produced by <code>git diff</code> on <code>file.txt</code> - that is, remove the second line, insert <code>// new test</code> as the fourth line, remove the last line, and add instead a line with the same content and <code>!</code> - you will get the content of <code>new_file.txt</code>.</p>
<p>Another important thing to note is that a patch is <strong>asymmetric</strong>: the patch from <code>file.txt</code> to <code>new_file.txt</code> is not the same as the patch for the other direction. Generating a patch between <code>new_file.txt</code> and <code>file.txt</code>, in this order, would mean exactly the opposite instructions than before - add the second line instead of removing it, and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/patch_asymmetric.png" alt="A patch consists of asymmetric instructions to get from one file to another" width="600" height="400" loading="lazy">
<em>A patch consists of asymmetric instructions to get from one file to another</em></p>
<p>Try it out:</p>
<pre><code class="lang-bash">git diff --no-index new_file.txt file.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_2.png" alt="Running git diff in the reverse direction yields the reverse instructions - add a line instead of removing it, and so on" width="600" height="400" loading="lazy">
<em>Running git diff in the reverse direction yields the reverse instructions - add a line instead of removing it, and so on</em></p>
<p>The patch format uses context, as well as line numbers, to locate differing file regions. This allows a patch to be applied to a somewhat earlier or later version of the first file than the one from which it was derived, as long as the applying program can still locate the context of the change. We will see exactly how these are used.</p>
<h3 id="heading-the-structure-of-a-diff">The Structure of a Diff</h3>
<p>It's time to dive deeper.</p>
<p>Generate a diff from <code>file.txt</code> to <code>new_file.txt</code> again, and consider the output more carefully:</p>
<pre><code class="lang-bash">git diff --no-index file.txt new_file.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_1-1.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git diff --no-index file.txt new_file.txt</code>_</p>
<p>The first line introduces the compared files. Git always gives one file the name <code>a</code>, and the other the name <code>b</code>. So in this case <code>file.txt</code> is called <code>a</code>, whereas <code>new_file.txt</code> is called <code>b</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_structure_1.png" alt="The first line in 's output introduces the files being compared" width="600" height="400" loading="lazy">
<em>The first line in <code>diff</code>'s output introduces the files being compared</em></p>
<p>Then the second line, starting with <code>index</code>, includes the blob SHAs of these files. So even though in our case they are not even stored within a Git repo, Git shows their corresponding SHA-1 values.</p>
<p>The third value in this line, <code>100644</code>, is the "mode bits", indicating that this is a "regular" file: not executable and not a symbolic link.</p>
<p>The use of two dots (<code>..</code>) here between the blob SHAs is just as a separator (unlike other cases where it's used within Git).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_structure_2.png" alt="The second line in 's output includes the blob SHAs of the compared files, as well as the mode bits" width="600" height="400" loading="lazy">
<em>The second line in <code>diff</code>'s output includes the blob SHAs of the compared files, as well as the mode bits</em></p>
<p>Other header lines might indicate the old and new mode bits if they've changed, old and new filenames if the files were being renamed, and so on.</p>
<p>The blob SHAs (also called "blob IDs") are helpful if this patch is later applied by Git to the same project and there are conflicts while applying it. You will better understand what this means when you learn about the merges in <a class="post-section-overview" href="#heading-chapter-7-understanding-git-merge">the next chapter</a>.</p>
<p>After the blob IDs, we have two lines: one starting with <code>-</code> signs, and the other starting with <code>+</code> signs. This is the traditional "unified diff" header, again showing the files being compared and the direction of the changes: <code>-</code> signs show lines in the A version that are missing from the B version, and <code>+</code> signs show lines missing in the A version but present in B.</p>
<p>If the patch were of this file being added or deleted in its entirety, then one of these would be <code>/dev/null</code> to signal that.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_structure_3.png" alt=" signs show lines in the A version but missing from the B version; and  signs, lines missing in A version but present in B" width="600" height="400" loading="lazy">
<em><code>-</code> signs show lines in the A version but missing from the B version, and <code>+</code> signs, lines missing in A version but present in B</em></p>
<p>Consider the case where you delete a file:</p>
<pre><code class="lang-bash">rm awesome.txt
</code></pre>
<p>And then use <code>git diff</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/rm_diff.png" alt="'s output for a deleted file" width="600" height="400" loading="lazy">
<em><code>git diff</code>'s output for a deleted file</em></p>
<p>The <code>A</code> version, representing the state of the index, is currently <code>awesome.txt</code>, compared to the working dir where this file does not exist, so it is <code>/dev/null</code>. All lines are preceded by <code>-</code> signs as they exist only in the <code>A</code> version.</p>
<p>For now, undo the deleting (more on undoing changes in Part 3):</p>
<pre><code class="lang-bash">git restore awesome.txt
</code></pre>
<p>Going back to the diff we started with:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_1-2.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git diff --no-index file.txt new_file.txt</code>_</p>
<p>After this unified diff header, we get to the main part of the diff, consisting of "difference sections", also called "hunks" or "chunks" in Git. Note that these terms are used interchangeably, and you may stumble upon either of them in Git's documentation and tutorials, as well as Git's source code.</p>
<p>Every hunk begins with a single line, starting with two <code>@</code> signs. These signs are followed by at most four numbers, and then a header for the chunk - which is an educated guess by Git. Usually, it will include the beginning of a function or a class, when possible.</p>
<p>In this example it doesn't include anything as this is a text file, so consider another example for a moment:</p>
<pre><code class="lang-bash">git diff --no-index example.py example_changed.py
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_example_changed.png" alt="When possible, Git includes a header for each hunk, for example a function or class definition" width="600" height="400" loading="lazy">
<em>When possible, Git includes a header for each hunk, for example a function or class definition</em></p>
<p>In the image above, the hunk's header includes the beginning of the function that includes the changed lines - <code>def example_function(x)</code>.</p>
<p>Back to our previous example then:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_1-3.png" alt="Back to the previous diff" width="600" height="400" loading="lazy">
<em>Back to the previous diff</em></p>
<p>After the two <code>@</code> signs, you'll find four numbers:</p>
<p>The first numbers are preceded by a <code>-</code> sign as they refer to <code>file A</code>. The first number represents the line number corresponding to the first line in <code>file A</code> that this hunk refers to. In the example above, it is <code>1</code>, meaning that the line <code>This is a file</code> corresponds to line number <code>1</code> in version <code>file A</code>.</p>
<p>This number is followed by a comma (<code>,</code>), and then the number of lines this chunk consists of in <code>file A</code>. This number includes all context lines (the lines preceded with a space in the <code>diff</code>), or lines marked with a <code>-</code> sign, as they are part of <code>file A</code>, but not lines marked with a <code>+</code> sign, as they do not exist in <code>file A</code>.</p>
<p>In our example, this number is <code>6</code>, counting the context line <code>This is a file</code>, the <code>-</code> line <code>It has a nice poem:</code>, then the three context lines, and lastly <code>Are belong to you</code>.</p>
<p>As you can see, the lines beginning with a space character are context lines, which means they appear as shown in both <code>file A</code> and <code>file B</code>.</p>
<p>Then, we have a <code>+</code> sign to mark the two numbers that refer to <code>file B</code>. First, there's the line number corresponding to the first line in <code>file B</code>, followed by the number of lines this chunk consists of in <code>file B</code>.</p>
<p>This number includes all context lines, as well as lines marked with the <code>+</code> sign, as they are part of <code>file B</code>, but not lines marked with a <code>-</code> sign.</p>
<p>These four numbers are followed by two additional <code>@</code> signs.</p>
<p>After the header of the chunk, we get the actual lines - either context, <code>-</code>, or <code>+</code> lines.</p>
<p>Typically and by default, a hunk starts and ends with three context lines. For example, if you modify lines 4-5 in a file with ten lines:</p>
<ul>
<li>Line 1 - context line (before the changed lines)</li>
<li>Line 2 - context line (before the changed lines)</li>
<li>Line 3 - context line (before the changed lines)</li>
<li>Line 4 - changed line</li>
<li>Line 5 - another changed line</li>
<li>Line 6 - context line (after the changed lines)</li>
<li>Line 7 - context line (after the changed lines)</li>
<li>Line 8 - context line (after the changed lines)</li>
<li>Line 9 - this line will not be part of the hunk</li>
</ul>
<p>So by default, changing lines 4-5 results in a hunk consisting of lines 1-8, that is, three lines before and three lines after the modified lines.</p>
<p>If that file doesn't have nine lines, but rather six lines - then the hunk will contain only one context line after the changed lines, and not three. Similarly, if you change the second line of a file, then there would be only one line of context before the changed lines.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_structure_4.png" alt="The patch format by " width="600" height="400" loading="lazy">
<em>The patch format by <code>git diff</code></em></p>
<h3 id="heading-how-to-produce-diffs">How to Produce Diffs</h3>
<p>The last example we considered shows a diff between two files. A single patch file can contain the differences for <em>any</em> number of files, and <code>git diff</code> produces diffs for all altered files in the repository in a single patch.</p>
<p>Often, you will see the output of <code>git diff</code> showing two versions of the same file and the difference between them.</p>
<p>To demonstrate, consider the state in another branch called <code>diffs</code>:</p>
<pre><code class="lang-bash">git checkout diffs
</code></pre>
<p>Again, I encourage you to run the commands with me - make sure you clone the repository from:</p>
<p><a target="_blank" href="https://github.com/Omerr/gitting_things_repo.git">https://github.com/Omerr/gitting_things_repo.git</a></p>
<p>At the current state, the active directory is a Git repository, with a clean status:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_branch_diffs.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git status</code></em></p>
<p>Take an existing file, <code>my_file.py</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/nano_my_file.png" alt="An example file - " width="600" height="400" loading="lazy">
_An example file - <code>my_file.py</code>_</p>
<p>And change the second line from <code>print('An example function!')</code> to <code>print('An example function! And it has been changed!')</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/nano_my_file_after_change.png" alt="The contents of  after modifying the second line" width="600" height="400" loading="lazy">
_The contents of <code>my_file.py</code> after modifying the second line_</p>
<p>Save your changes, but don't stage or commit them. Next, run <code>git diff</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_my_file.png" alt="The output of  for  after changing it" width="600" height="400" loading="lazy">
_The output of <code>git diff</code> for <code>my_file.py</code> after changing it_</p>
<p>The output of <code>git diff</code> shows the difference between <code>my_file.py</code>'s version in the staging area, which in this case is the same as the last commit (<code>HEAD</code>), and the version in the working directory.</p>
<p>I covered the terms "working directory", "staging area", and "commit" in the <a class="post-section-overview" href="#heading-chapter-1-git-objects">Git objects chapter</a>, so check it out in ccase you would like to refresh your memory. As a reminder, the terms "staging area" and "index" are interchangeable, and both are widely used.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/repo_state_commit_2_staging_area.png" alt="At this state, the status of the working dir is different from the status of the index. The status of the index is the same as that of " width="600" height="400" loading="lazy">
<em>At this state, the status of the working dir is different from the status of the index. The status of the index is the same as that of <code>HEAD</code></em></p>
<p>To see the difference between the <strong>working dir</strong> and the <strong>staging area</strong>, use <code>git diff</code>, without any additional flags.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/repo_state_commit_2_git_diff-1.png" alt="Without switches,  shows the difference between the staging area and the working directory" width="600" height="400" loading="lazy">
<em>Without switches, <code>git diff</code> shows the difference between the staging area and the working directory</em></p>
<p>As you can see, <code>git diff</code> lists here both <code>file A</code> and <code>file B</code> pointing to <code>my_file.py</code>. <code>file A</code> here refers to the version of <code>my_file.py</code> in the staging area, whereas <code>file B</code> refers to its version in the working dir.</p>
<p>Note that if you modify <code>my_file.py</code> in a text editor, and don't save the file, then <code>git diff</code> will not be aware of the changes you've made. This is because they haven't been saved to the working dir.</p>
<p>We can provide a few switches to <code>git diff</code> to get the diff between the working dir and a specific commit, or between the staging area and the latest commit, or between two commits, and so on.</p>
<p>First create a new file, <code>new_file.txt</code>, and save it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/nano_new_file.png" alt="A simple new file saved as new_file.txt" width="600" height="400" loading="lazy">
_A simple new file saved as <code>new_file.txt</code>_</p>
<p>Currently the file is in the working dir, and it is actually untracked in Git.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_file_working_dir.png" alt="A new, untracked file" width="600" height="400" loading="lazy">
<em>A new, untracked file</em></p>
<p>Now stage and commit this file:</p>
<pre><code class="lang-bash">git add new_file.txt
git commit -m <span class="hljs-string">"Commit 3"</span>
</code></pre>
<p>Now, the state of <code>HEAD</code> is the same as the state of the staging area, as well as the working tree:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/repo_state_commit_3.png" alt="The state of HEAD is the same as the index and the working dir" width="600" height="400" loading="lazy">
<em>The state of <code>HEAD</code> is the same as the index and the working dir</em></p>
<p>Next, edit <code>new_file.txt</code> by adding a new line at the beginning and another new line at the end:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_file_edited.png" alt="Modifying  by adding a line in the beginning and another in the end" width="600" height="400" loading="lazy">
_Modifying <code>new_file.txt</code> by adding a line in the beginning and another in the end_</p>
<p>As a result, the state is as follows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/repo_state_start_end.png" alt="After saving, the state in the working dir is different than that of the index or " width="600" height="400" loading="lazy">
<em>After saving, the state in the working dir is different than that of the index or <code>HEAD</code></em></p>
<p>A nice trick would be to use <code>git add -p</code>, which allows you to split the changes even within a file, and consider which ones you'd like to stage.</p>
<p>In this case, add the first line to the index, but not the last line. To do that, you can split the hunk using <code>s</code>, then accept to stage the first hunk (using <code>y</code>), and not the second part (using <code>n</code>).</p>
<p>If you are not sure what each letter stands for, you can always use a <code>?</code> and Git will tell you.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/add_p.png" alt="Using , you can stage only the first change" width="600" height="400" loading="lazy">
<em>Using <code>git add -p</code>, you can stage only the first change</em></p>
<p>So now the state in <code>HEAD</code> is without either of those new lines. In the staging area you have the first line but not the last line, and in the working dir you have both new lines.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/repo_state_after_add_p.png" alt="The state after staging only the first line" width="600" height="400" loading="lazy">
<em>The state after staging only the first line</em></p>
<p>If you use <code>git diff</code>, what will happen?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_3.png" alt=" shows the difference between the index and the working dir" width="600" height="400" loading="lazy">
<em><code>git diff</code> shows the difference between the index and the working dir</em></p>
<p>Well, as stated before, you get the diff between the staging area and the working tree.</p>
<p>What happens if you want to get the diff between <code>HEAD</code> and the staging area? For that, you can use <code>git diff --cached</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_cached.png" alt=" shows the difference between  and the index" width="600" height="400" loading="lazy">
<em><code>git diff --cached</code> shows the difference between <code>HEAD</code> and the index</em></p>
<p>And what if you want the difference between <code>HEAD</code> and the working tree? For that you can run <code>git diff HEAD</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_HEAD.png" alt=" shows the difference between  and the working dir" width="600" height="400" loading="lazy">
<em><code>git diff HEAD</code> shows the difference between <code>HEAD</code> and the working dir</em></p>
<p>To summarize the different switches for git diff we have seen so far, here's a diagram:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_diagram_1.png" alt="Different switches for " width="600" height="400" loading="lazy">
<em>Different switches for <code>git diff</code></em></p>
<p>As a reminder, at the beginning of this chapter you used <code>git diff --no-index</code>. With the <code>--no-index</code> switch, you can compare two files that are not part of the repository - or of any staging area.</p>
<p>Now, commit the changes you have in the staging area:</p>
<pre><code class="lang-bash">git commit -m <span class="hljs-string">"Commit 4"</span>
</code></pre>
<p>To observe the diff between this commit and its parent commit, you can run the following command:</p>
<pre><code class="lang-bash">git diff HEAD~1 HEAD
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_HEAD_1_HEAD.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git diff HEAD~1 HEAD</code></em></p>
<p>By the way, you can omit the <code>1</code> above and write <code>HEAD~</code>, and get the same result. Using <code>1</code> is the explicit way to state you are referring to the first parent of the commit.</p>
<p>Note that writing the parent commit here, <code>HEAD~1</code>, first results in a diff showing how to get <em>from</em> the parent commit <em>to</em> the current commit. Of course, I could also generate the reverse diff by writing:</p>
<pre><code class="lang-bash">git diff HEAD HEAD~1
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_HEAD_HEAD_1.png" alt="The output of  generates the reverse patch" width="600" height="400" loading="lazy">
<em>The output of <code>git diff HEAD HEAD~1</code> generates the reverse patch</em></p>
<p>To summarize all the different switches for git diff we covered in this section, see this diagram:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_diagram_2.png" alt="The different switches for " width="600" height="400" loading="lazy">
<em>The different switches for <code>git diff</code></em></p>
<p>A short way to view the diff between a commit and its parent is by using <code>git show</code>, for example:</p>
<pre><code class="lang-bash">git show HEAD
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_show_HEAD.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git show HEAD</code></em></p>
<p>This is the same as writing:</p>
<pre><code class="lang-bash">git diff HEAD~ HEAD
</code></pre>
<p>We can now update our diagram:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_diagram_3.png" alt=" is used to show the difference between commits" width="600" height="400" loading="lazy">
<em><code>git diff HEAD~ HEAD</code> is used to show the difference between commits</em></p>
<p>You can go back to this diagram as a reference when needed.</p>
<p>As a reminder, Git commits are snapshots - of the entire working directory of the repository, at a certain point in time. Yet, it's sometimes not useful to regard a commit as a whole snapshot, but rather by the <strong>changes</strong> this specific commit introduced. In other words, by the diff between a parent commit to the next commit.</p>
<p>As you learned in the <a class="post-section-overview" href="#heading-chapter-1-git-objects">Git Objects chapter</a>, Git stores the <strong>entire</strong> snapshots. The diff is dynamically generated from the snapshot data - by comparing the root trees of the commit and its parent.</p>
<p>Of course, Git can compare any two snapshots in time, not just adjacent commits, and also generate a diff of files not included in a repository.</p>
<h3 id="heading-how-to-apply-patches">How to Apply Patches</h3>
<p>By using <code>git diff</code> you can see a patch Git generates, and you can then apply this patch using <code>git apply</code>.</p>
<h4 id="heading-historical-note">Historical Note</h4>
<p>Actually, sharing patches used to be the main way to share code in the early days of open source. But now - virtually all projects have moved to sharing Git commits directly through pull requests (called "merge requests" on some platforms).</p>
<p>The biggest problem with using patches is that it is hard to apply a patch when your working directory does not match the sender's previous commit. Losing the commit history makes it difficult to resolve conflicts. You will better understand this as you dive deeper into the process of <code>git apply</code>, especially in the next chapter where we cover merges.</p>
<h4 id="heading-a-simple-patch">A Simple Patch</h4>
<p>What does it mean to apply a patch? It's time to try it out!</p>
<p>Take the output of <code>git diff</code>:</p>
<pre><code class="lang-bash">git diff HEAD~1 HEAD
</code></pre>
<p>And store it in a file:</p>
<pre><code class="lang-bash">git diff HEAD~1 HEAD &gt; my_patch.patch
</code></pre>
<p>Use <code>reset</code> to undo the last commit:</p>
<pre><code class="lang-bash">git reset --hard HEAD~1
</code></pre>
<p>Don't worry about the last command - I'll explain it in detail in Part 3, where we discuss undoing changes. In short, it allows us to "reset" the state of where <code>HEAD</code> is pointing to, as well as the state of the index and of the working dir. In the example above, they are all set to the state of <code>HEAD~1</code>, or "Commit 3" in the diagram.</p>
<p>So after running the reset command, the contents of the file are as follows (the state from "Commit 3"):</p>
<pre><code class="lang-bash">nano new_file.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/nano_new_file-1.png" alt="Image" width="600" height="400" loading="lazy">
_<code>new_file.txt</code>_</p>
<p>And you will apply this patch that you've just saved:</p>
<pre><code class="lang-bash">nano my_patch.patch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/my_patch.png" alt="The patch you are about to apply, as generated by git diff" width="600" height="400" loading="lazy">
<em>The patch you are about to apply, as generated by git diff</em></p>
<p>This patch tells Git to find the lines:</p>
<pre><code class="lang-txt">This is a new file
With new content!
</code></pre>
<p>Those lines used to be line number 1 and line number 2 in <code>new_file.txt</code>, and add a line with the content <code>START!</code> right above them.</p>
<p>Run this command to apply the patch:</p>
<pre><code class="lang-bash">git apply my_patch.patch
</code></pre>
<p>And as a result, you get this version of your file, just like the commit you have created before:</p>
<pre><code class="lang-bash">nano new_file.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_file_after_applying.png" alt="The contents of  after applying the patch" width="600" height="400" loading="lazy">
_The contents of <code>new_file.txt</code> after applying the patch_</p>
<h4 id="heading-understanding-the-context-lines">Understanding the Context Lines</h4>
<p>To understand the importance of context lines, consider a more advanced scenario. What happens if line numbers have changed since you created the patch file?</p>
<p>To test, start by creating another file:</p>
<pre><code class="lang-bash">nano test.text
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/testing_file.png" alt="Creating another file - " width="600" height="400" loading="lazy">
<em>Creating another file - <code>test.txt</code></em></p>
<p>Stage and commit this file:</p>
<pre><code class="lang-bash">git add test.txt

git commit -m <span class="hljs-string">"Test file"</span>
</code></pre>
<p>Now, change this file by adding a new line, and also erasing the line before the last one:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/testing_file_modified.png" alt="Changes to " width="600" height="400" loading="lazy">
<em>Changes to <code>test.txt</code></em></p>
<p>Observe the difference between the original version of the file and the version including your changes:</p>
<pre><code class="lang-bash">git diff -- test.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/testing_file_diff.png" alt="The output for git diff -- " width="600" height="400" loading="lazy">
<em>The output for <code>git diff -- test.txt</code></em></p>
<p>(Using <code>-- test.txt</code> tells Git to run the command <code>diff</code>, taking into consideration only <code>test.txt</code>, so you don't get the diff for other files.)</p>
<p>Store this diff into a patch file:</p>
<pre><code class="lang-bash">git diff -- test.txt &gt; new_patch.patch
</code></pre>
<p>Now, reset your state to that before introducing the changes:</p>
<pre><code class="lang-bash">git reset --hard
</code></pre>
<p>If you were to apply new_patch.patch now, it would simply work.</p>
<p>Let's now consider a more interesting case. Modify <code>test.txt</code> again by adding a new line at the beginning:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/testing_file_added_first_line.png" alt="Adding a new line at the beginning of " width="600" height="400" loading="lazy">
<em>Adding a new line at the beginning of <code>test.txt</code></em></p>
<p>As a result, the line numbers are different from the original version where the patch has been created. Consider the patch you created before:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_patch.png" alt="Image" width="600" height="400" loading="lazy">
_<code>new_patch.patch</code>_</p>
<p>It assumes that the line <code>With more text</code> is the second line in <code>test.txt</code>, which is no longer the case. So...will <code>git apply</code> work?</p>
<pre><code class="lang-bash">git apply new_patch.patch
</code></pre>
<p>It worked!</p>
<p>By default, Git looks for 3 lines of context before and after each change introduced in the patch - as you can see, they are included in the patch file. If you take three lines before and after the added line, and three lines before and after the deleted line (actually only one line after, as no other lines exist) - you get to the patch file. If these lines all exist - then applying the patch works, even if the line numbers changed.</p>
<p>Reset the state again:</p>
<pre><code class="lang-bash">git reset --hard
</code></pre>
<p>What happens if you change one of the context lines? Try it out by changing the line <code>With more text</code> to <code>With more text!</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/testing_file_modifying_second_line.png" alt="Changing the line  to " width="600" height="400" loading="lazy">
<em>Changing the line <code>With more text</code> to <code>With more text!</code></em></p>
<p>And now:</p>
<pre><code class="lang-bash">git apply new_patch.patch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_apply_new_patch.png" alt=" doesn't apply the patch" width="600" height="400" loading="lazy">
<em><code>git apply</code> doesn't apply the patch</em></p>
<p>Well, no. The patch does not apply. If you are not sure why, or just want to better understand the process Git is performing, you can add the <code>--verbose</code> flag to <code>git apply</code>, like so:</p>
<pre><code class="lang-bash">git apply --verbose new_patch.patch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_apply_new_patch_verbose.png" alt=" shows the process Git is taking to apply the patch" width="600" height="400" loading="lazy">
<em><code>git apply --verbose</code> shows the process Git is taking to apply the patch</em></p>
<p>It seems that Git searched lines from the file, including the line "With more text", right before the line "It has some really nice lines". This sequence of lines no longer exists in the file. As Git cannot find this sequence, it cannot apply the patch.</p>
<p>As mentioned earlier, by default, Git looks for 3 lines of context before and after each change introduced in the patch. If the surrounding three lines do not exist, Git cannot apply the patch.</p>
<p>You can ask Git to rely on fewer lines of context, using the <code>-C</code> argument. For example, to ask Git to look for 1 line of the surrounding context, run the following command:</p>
<pre><code class="lang-bash">git apply -C1 new_patch.patch
</code></pre>
<p>The patch applies!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_apply_c1.png" alt="Image" width="600" height="400" loading="lazy">
_<code>git apply -C1 new_patch.patch</code>_</p>
<p>Why is that? Consider the patch again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_patch-1.png" alt="Image" width="600" height="400" loading="lazy">
_<code>new_patch.patch</code>_</p>
<p>When applying the patch with the <code>-C1</code> option, Git is looking for the lines:</p>
<pre><code class="lang-txt">Like this one
And that one
</code></pre>
<p>in order to add the line <code>!!!This is the new line!!!</code> between these two lines. These lines exist (and, importantly, they appear one right after the other). As a result, Git can successfully add the line between them, even though the line numbers changed.</p>
<p>Similarly, Git would look for the lines:</p>
<pre><code class="lang-txt">How wonderful
So we are writing an example
Git is awesoome!
</code></pre>
<p>As Git can find these lines, Git can erase the middle one.</p>
<p>If we changed one of these lines, say, changed "How wonderful" to "How very wondeful", then Git would not be able to find the string above, and thus the patch would not apply.</p>
<h3 id="heading-recap-git-diff-and-patch">Recap - Git Diff and Patch</h3>
<p>In this chapter, you learned what a diff is, and the difference between a diff and a patch. You learned how to generate various patches using different switches for <code>git diff</code>. You also learned what the output of git diff looks like, and how it is constructed. Ultimately, you learned how patches are applied, and specifically the importance of context.</p>
<p>Understanding diffs is a major milestone for understanding many other processes within Git - for example, merging or rebasing, that we will explore in the next chapters.</p>
<h2 id="heading-chapter-7-understanding-git-merge">Chapter 7 - Understanding Git Merge</h2>
<p>By reading this chapter, you are going to really understand <code>git merge</code>, one of the most common operations you'll perform in your Git repositories.</p>
<h3 id="heading-what-is-a-merge-in-git">What is a Merge in Git?</h3>
<p>Merging is the process of combining the recent changes from several branches into a single new commit. This commit points back to these branches.</p>
<p>In a way, merging is the complement of branching in version control: a branch allows you to work simultaneously with others on a particular set of files, whereas a merge allows you to later combine separate work on branches that diverged from a common ancestor commit.</p>
<p>OK, let's take this bit by bit.</p>
<p>Remember that in Git, a branch is just a name pointing to a single commit. When we think about commits as being "on" a specific branch, they are actually reachable through the parent chain from the commit that the branch is pointing to.</p>
<p>That is, if you consider this commit graph:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_graph_1.png" alt="Commit graph with " width="600" height="400" loading="lazy">
_Commit graph with <code>feature_1</code>_</p>
<p>You see the branch <code>feature_1</code>, which points to a commit with the SHA-1 value of <code>ba0d2</code>. As in previous chapters, I only write the first 5 digits of the SHA-1 value for brevity.</p>
<p>Notice that commit <code>54a9d</code> is also "on" this branch, as it is the parent commit of <code>ba0d2</code>. So if you start from the pointer of <code>feature_1</code>, you get to <code>ba0d2</code>, which then points to <code>54a9d</code>. You can go on the chain of parents, and all these reachable commits are considered to be "on" <code>feature_1</code>.</p>
<p>When you merge with Git, you merge commits. Almost always, we merge two commits by referring to them with the branch names that point to them. Thus we say we "merge branches" - though under the hood, we actually merge commits.</p>
<h3 id="heading-time-to-get-hands-on-1">Time to Get Hands-on</h3>
<p>For this chapter, I will use the following repository:</p>
<p><a target="_blank" href="https://github.com/Omerr/gitting_things_merge.git">https://github.com/Omerr/gitting_things_merge.git</a></p>
<p>As in previous chapters, I encourage you to clone it locally and have the same starting point I am using for this chapter.</p>
<p>OK, so let's say I have this simple repository here, with a branch called <code>main</code>, and a few commits with the commit messages of "Commit 1", "Commit 2", and "Commit 3":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commits_1_3.png" alt="A simple repository with three commits" width="600" height="400" loading="lazy">
<em>A simple repository with three commits</em></p>
<p>Next, create a feature branch by typing <code>git branch new_feature</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_branch_new_feature.png" alt="Creating a new branch with " width="600" height="400" loading="lazy">
<em>Creating a new branch with <code>git branch</code></em></p>
<p>And switch <code>HEAD</code> to point to this new branch, by using <code>git checkout new_feature</code> (or <code>git switch new_feature</code>). You can look at the outcome by using git log:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_checkout_new_feature.png" alt="The output of  after using " width="600" height="400" loading="lazy">
_The output of <code>git log</code> after using <code>git checkout new_feature</code>_</p>
<p>As a reminder, you could also write <code>git checkout -b new_feature</code>, which would both create a new branch and change <code>HEAD</code> to point to this new branch.</p>
<p>If you need a reminder about branches and how they're implemented under the hood, please check out <a class="post-section-overview" href="#heading-chapter-2-branches-in-git">chapter 2</a>. Yes, check out. Pun intended 😇</p>
<p>Now, on the <code>new_feature</code> branch, implement a new feature. In this example, I will edit an existing file that looks like this before the edit:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_before_changes.png" alt=" before editing it" width="600" height="400" loading="lazy">
<em><code>code.py</code> before editing it</em></p>
<p>And I will now edit it to include a new function:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_new_feature.png" alt="Implementing " width="600" height="400" loading="lazy">
_Implementing <code>new_feature</code>_</p>
<p>And luckily, this is not a programming book, so this function is legit 😇</p>
<p>Next, stage and commit this change:</p>
<pre><code class="lang-bash">git add code.py

git commit -m <span class="hljs-string">"Commit 4"</span>
</code></pre>
<p>Looking at the history, you have the <code>branch new_feature</code>, now pointing to "Commit 4", which points to its parent, "Commit 3". The branch main is also pointing to "Commit 3".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commits_1_4.png" alt="The history after committing &quot;Commit 4&quot;" width="600" height="400" loading="lazy">
<em>The history after committing "Commit 4"</em></p>
<p>Time to merge the new feature! That is, merge these two branches, <code>main</code> and <code>new_feature</code>. Or, in Git's lingo, merge <code>new_feature</code> <em>into</em> <code>main</code>. This means merging "Commit 4" and "Commit 3". This is pretty trivial, as after all, "Commit 3" is an ancestor of "Commit 4".</p>
<p>Check out the main branch (with <code>git checkout main</code>), and perform the merge by using <code>git merge new_feature</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_merge_new_feature.png" alt="Merging  into " width="600" height="400" loading="lazy">
_Merging <code>new_feature</code> into <code>main</code>_</p>
<p>Since <code>new_feature</code> never really diverged from main, Git could just perform a fast-forward merge. So what happened here? Consider the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_ff_merge.png" alt="The result of a fast-forward merge" width="600" height="400" loading="lazy">
<em>The result of a fast-forward merge</em></p>
<p>Even though you used <code>git merge</code>, there was no actual merging here. Actually, Git did something very simple - it <code>reset</code> the main branch to point to the same commit as the branch <code>new_feature</code>.</p>
<p>In case you don't want that to happen, but rather you want Git to really perform a merge, you could either change Git's configuration, or run the merge command with the <code>--no-ff</code> flag.</p>
<p>First, undo the last commit:</p>
<pre><code class="lang-bash">git reset --hard HEAD~1
</code></pre>
<p>Reminder: if this way of using reset is not clear to you, don't worry - we will cover it in detail in Part 3. It is not crucial for this introduction of merge, though. For now, it's important to understand that it basically undoes the merge operation.</p>
<p>Just to clarify, now if you checked out <code>new_feature</code> again:</p>
<pre><code class="lang-bash">git checkout new_feature
</code></pre>
<p>The history would look just like before the merge:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_reset_after_merge.png" alt="The history after using " width="600" height="400" loading="lazy">
<em>The history after using <code>git reset --hard HEAD~1</code></em></p>
<p>Next, perform the merge with the <code>--no-fast-forward</code> flag (<code>--no-ff</code> for short):</p>
<pre><code class="lang-bash">git checkout main
git merge new_feature --no-ff
</code></pre>
<p>Now, if we look at the history using <code>git lol</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_lol_1.png" alt="History after merging with the  flag" width="600" height="400" loading="lazy">
<em>History after merging with the <code>--no-ff</code> flag</em></p>
<p>(Reminder: <code>git lol</code> is an alias I added to Git to visibly see the history in a graphical manner. You can find it, along with the other components of my setup, at the <a class="post-section-overview" href="#heading-my-setup">My Setup</a> part of the <a class="post-section-overview" href="#heading-introduction">Introduction</a> chapter.)</p>
<p>Considering this history, you can see Git created a new commit, a merge commit.</p>
<p>If you consider this commit a bit closer:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> -n1
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_after_lol_1.png" alt="The merge commit has two parents" width="600" height="400" loading="lazy">
<em>The merge commit has two parents</em></p>
<p>You will see that this commit actually has two parents - "Commit 4", which was the commit that <code>new_feature</code> pointed to when you ran <code>git merge</code>, and "Commit 3", which was the commit that <code>main</code> pointed to.</p>
<p><strong>A merge commit has two parents: the two commits it merged.</strong></p>
<p>The merge commit shows us the concept of merge quite well. Git takes two commits, usually referenced by two different branches, and merges them together.</p>
<p>After the merge, as you started the process from <code>main</code>, you are still on <code>main</code>, and the history from <code>new_feature</code> has been <em>merged</em> into this branch. Since you started with <code>main</code>, then "Commit 3", which <code>main</code> pointed to, is the first parent of the merge commit, whereas "Commit 4", which you merged into <code>main</code>, is the second parent of the merge commit.</p>
<p>Notice that you started on <code>main</code> when it pointed to "Commit 3", and Git went quite a long way for you. It changed the working tree, the index, and also <code>HEAD</code> and created a new commit object. At least when you use <code>git merge</code> without the <code>--no-commit</code> flag and when it's not a fast-forward merge, Git does all of that.</p>
<p>This was a super simple case, where the branches you merged didn't diverge at all. We will soon consider more interesting cases.</p>
<p>By the way, you can use <code>git merge</code> to merge more than two commits - actually, any number of commits. This is rarely done, and to adhere to the practicality principle of this book, I won't delve into it.</p>
<p>Another way to think of <code>git merge</code> is by joining two or more development histories together. That is, when you merge, you incorporate changes from the named commits, since the time their histories diverged <em>from</em> the current branch, <em>into</em> the current branch. I used the term "branch" here, but I am stressing this again - <strong>we are actually merging commits</strong>.</p>
<h3 id="heading-time-for-a-more-advanced-case">Time For a More Advanced Case</h3>
<p>Time to consider a more advanced case, which is probably the most common case where we use <code>git merge</code> explicitly - where you need to merge branches that did diverge from one another.</p>
<p>Assume we have two people working on this repo now, John and Paul.</p>
<p>John created a branch:</p>
<pre><code class="lang-bash">git checkout -b john_branch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_john_branch.png" alt="A new branch, " width="600" height="400" loading="lazy">
_A new branch, <code>john_branch</code>_</p>
<p>And John has written a new song in a new file, <code>lucy_in_the_sky_with_diamonds.md</code>. Well, I believe John Lennon didn't really write in Markdown format, or use Git for that matter, but let's pretend he did for this explanation.</p>
<pre><code class="lang-bash">git add lucy_in_the_sky_with_diamonds.md
git commit -m <span class="hljs-string">"Commit 5"</span>
</code></pre>
<p>While John was working on this song, Paul was also writing, on another branch. Paul had started from main:</p>
<pre><code class="lang-bash">git checkout main
</code></pre>
<p>And created his own branch:</p>
<pre><code class="lang-bash">git checkout -b paul_branch
</code></pre>
<p>And Paul wrote his song into a file called <code>penny_lane.md</code>. Paul staged and committed this file:</p>
<pre><code class="lang-bash">git add penny_lane.md
git commit -m <span class="hljs-string">"Commit 6"</span>
</code></pre>
<p>So now our history looks like this - where we have two different branches, branching out from <code>main</code>, with different histories:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_6.png" alt="The history after John and Paul committed" width="600" height="400" loading="lazy">
<em>The history after John and Paul committed</em></p>
<p>John is happy with his branch (that is, his song), so he decides to merge it into the <code>main</code> branch:</p>
<pre><code class="lang-bash">git checkout main
git merge john_branch
</code></pre>
<p>Actually, this is a fast-forward merge, as we have learned before. You can validate that by looking at the history (using <code>git lol</code>, for example):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/merge_after_commit_6.png" alt="Merging  into  results in a fast-forward merge" width="600" height="400" loading="lazy">
_Merging <code>john_branch</code> into <code>main</code> results in a fast-forward merge_</p>
<p>At this point, Paul also wants to merge his branch into <code>main</code>, but now a fast-forward merge is no longer relevant - there are two different histories here: the history of <code>main</code>'s and that of <code>paul_branch</code>'s. It's not that <code>paul_branch</code> only adds commits on top of main branch or vice versa.</p>
<p>Now things get interesting. 😎😎</p>
<p>First, let Git do the hard work for you. After that, we will understand what's actually happening under the hood.</p>
<pre><code class="lang-bash">git merge paul_branch
</code></pre>
<p>Consider the history now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/merge_after_commit_6_paul_branch.png" alt="When you merge , you get a new merge commit\label{fig-history-after-git-merge}" width="600" height="400" loading="lazy">
_When you merge <code>paul_branch</code>, you get a new merge commit_</p>
<p>What you have is a new commit, with two parents - "Commit 5" and "Commit 6".</p>
<p>In the working dir, you can see that both John's song as well as Paul's song are there (if you use <code>ls</code>, you will see both files in the working dir).</p>
<p>Nice, Git really did merge the changes for you. But how does that happen?</p>
<p>Undo this last commit:</p>
<pre><code class="lang-bash">git reset --hard HEAD~
</code></pre>
<h3 id="heading-how-to-perform-a-three-way-merge-in-git">How to Perform a Three-way Merge in Git</h3>
<p>It's time to understand what's really happening under the hood. 😎</p>
<p>What Git has done here is it called a <strong>3-way merge</strong>. In outlining the process of a 3-way merge, I will use the term "branch" for simplicity, but you should remember you could also merge two (or more) commits that are not referenced by a branch.</p>
<p>The 3-way merge process includes these stages:</p>
<p>First, Git locates the common ancestor of the two branches. That is, the common commit from which the merging branches most recently diverged. Technically, this is actually the first commit that is reachable from both branches. This commit is then called the merge base.</p>
<p>Second, Git calculates two diffs - one diff from the merge base to the first branch, and another diff from the merge base to the second branch. Git generates patches based on those diffs.</p>
<p>Third, Git applies both patches to the merge base using a 3-way merge algorithm. The result is the state of the new merge commit.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_way_merge.png" alt="The three steps of the 3-way merge algorithm: (1) locate the common ancestor; (2) calculate diffs from the merge base to the first branch, and from the merge base to the second branch; (3) apply both patches together" width="600" height="400" loading="lazy">
<em>The three steps of the 3-way merge algorithm: (1) locate the common ancestor (2) calculate diffs from the merge base to the first branch, and from the merge base to the second branch (3) apply both patches together</em></p>
<p>So, back to our example.</p>
<p>In the first step, Git looks from both branches - <code>main</code> and <code>paul_branch</code> - and traverses the history to find the first commit that is reachable from both. In this case, this would be… which commit?</p>
<p>Correct, the merge commit (the one with "Commit 3" and "Commit 4" as its parents).</p>
<p>If you are not sure, you can always ask Git directly:</p>
<pre><code class="lang-bash">git merge-base main paul_branch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_way_merge_base.png" alt="The merge base is the merge commit with &quot;Commit 3&quot; and &quot;Commit 4&quot; as its parents. Note: the previous commit merge is blurred as it is not reachable via the current history following the  command" width="600" height="400" loading="lazy">
<em>The merge base is the merge commit with "Commit 3" and "Commit 4" as its parents. Note: the previous commit merge is blurred as it is not reachable via the current history following the <code>reset</code> command</em></p>
<p>By the way, this is the most common and simple case, where we have a single obvious choice for the merge base. In more complicated cases, there may be multiple possibilities for a merge base, but this is not within our focus.</p>
<p>In the second step, Git calculates the diffs. So it first calculates the diff between the merge commit and "Commit 5":</p>
<pre><code class="lang-bash">git diff 4f90a62 4683aef
</code></pre>
<p>(The SHA-1 values will be different on your machine.)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_4_5.png" alt="The diff between the merge commit and &quot;Commit 5&quot;\label{fig-john-patch}" width="600" height="400" loading="lazy">
<em>The diff between the merge commit and "Commit 5"</em></p>
<p>If you don't feel comfortable with the output of <code>git diff</code>, you can read the previous chapter where I described it in detail.</p>
<p>You can store that diff to a file:</p>
<pre><code class="lang-bash">git diff 4f90a62 4683aef &gt; john_branch_diff.patch
</code></pre>
<p>Next, Git calculates the diff between the merge commit and "Commit 6":</p>
<pre><code class="lang-bash">git diff 4f90a62 c5e4951
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_4_6.png" alt="The diff between the merge commit and &quot;Commit 6&quot;" width="600" height="400" loading="lazy">
<em>The diff between the merge commit and "Commit 6"</em></p>
<p>Write this one to a file as well:</p>
<pre><code class="lang-bash">git diff 4f90a62 c5e4951 &gt; paul_branch_diff.patch
</code></pre>
<p>Now Git applies those patches on the merge base.</p>
<p>First, try that out directly - just apply the patches (I will walk you through it in a moment). This is not what Git really does under the hood, but it will help you gain a better understanding of why Git needs to do something different.</p>
<p>Checkout the merge base first, that is, the merge commit:</p>
<pre><code class="lang-bash">git checkout 4f90a62
</code></pre>
<p>And apply John's patch first (as a reminder, this is the patch shown in the image with the caption "The diff between the merge commit and "Commit 5""):</p>
<pre><code class="lang-bash">git apply --index john_branch_diff.patch
</code></pre>
<p>Notice that for now there is no merge commit. <code>git apply</code> updates the working dir as well as the index, as we used the <code>--index</code> switch.</p>
<p>You can observe the status using <code>git status</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_apply_john.png" alt="Applying John's patch on the merge commit" width="600" height="400" loading="lazy">
<em>Applying John's patch on the merge commit</em></p>
<p>So now John's new song is incorporated into the index. Apply the other patch:</p>
<pre><code class="lang-bash">git apply --index paul_branch_diff.patch
</code></pre>
<p>As a result, the index contains changes from both branches.</p>
<p>Now it's time to commit your merge. Since the porcelain command <code>git commit</code> always generates a commit with a single parent, you would need the underlying plumbing command - <code>git commit-tree</code>.</p>
<p>If you need a reminder about porcelain vs plumbing commands, check out <a class="post-section-overview" href="#heading-chapter-4-how-to-create-a-repo-from-scratch">chapter 4</a> where I explained these terms, and created an entire repo from scratch.</p>
<p>Remember that every Git commit object points to a single tree. So you need to record the contents of the index in a tree:</p>
<pre><code class="lang-bash">git write-tree
</code></pre>
<p>Now you get the SHA-1 value of the created tree, and you can create a commit object using <code>git commit-tree</code>:</p>
<pre><code class="lang-bash">git commit-tree &lt;TREE_SHA&gt; -p &lt;COMMIT_5&gt; -p &lt;COMMIT_6&gt; -m <span class="hljs-string">"Merge commit!"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_merge_commit.png" alt="Creating a merge commit" width="600" height="400" loading="lazy">
<em>Creating a merge commit</em></p>
<p>Great, so you have created a commit object!</p>
<p>Recall that <code>git merge</code> also changes <code>HEAD</code> to point to the new merge commit object. So you can simply do the same:</p>
<pre><code class="lang-bash">git reset --hard db315a
</code></pre>
<p>If you look at the history now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_reset_to_merge_commit_git_lol.png" alt="The history after creating a merge commit and resetting " width="600" height="400" loading="lazy">
<em>The history after creating a merge commit and resetting <code>HEAD</code></em></p>
<p>(Note: in this state, <code>HEAD</code> is "detached" - that is, it directly points to a commit object rather than a named reference. <code>gg</code> does not show <code>HEAD</code> when it is "detached", so don't be confused if you can't see <code>HEAD</code> in the output of <code>gg</code>.)</p>
<p>This is almost what we wanted. Remember that when you ran <code>git merge</code>, the result was <code>HEAD</code> pointing to <code>main</code> which pointed to the newly created commit (as shown in the image with the caption "When you merge <code>paul_branch</code>, you get a new merge commit". What should you do then?</p>
<p>Well, what you want is to modify <code>main</code>, so you can just point it to the new commit:</p>
<pre><code class="lang-bash">git checkout main
git reset --hard db315a
</code></pre>
<p>And now you have the same result as when you ran <code>git merge</code>: <code>main</code> points to the new commit, which has "Commit 5" and "Commit 6" as its parents. You can use <code>git lol</code> to verify that.</p>
<p>So this is exactly the same result as the merge done by Git, with the exception of the timestamp and thus the SHA-1 value, of course.</p>
<p>Overall, you got to merge both the contents of the two commits - that is, the state of the files, and also the history of those commits - by creating a merge commit that points to both histories.</p>
<p>In this simple case, you could actually just apply the patches using <code>git apply</code>, and everything works quite well.</p>
<h3 id="heading-quick-recap-of-a-three-way-merge">Quick Recap of a Three-way Merge</h3>
<p>So to quickly recap, on a three-way merge, Git:</p>
<ul>
<li>First, locates the merge base - the common ancestor of the two branches. That is, the first commit that is reachable from both branches.</li>
<li>Second, Git calculates two diffs - one diff from the merge base to the first branch, and another diff from the merge base to the second branch.</li>
<li>Third, Git applies both patches to the merge base, using a 3-way merge algorithm. I haven't explained the 3-way merge yet, but I will elaborate on that later. The result is the state of the new merge commit.</li>
</ul>
<p>You can also understand why it's called a "3-way merge": Git merges three different states - that of the first branch, that of the second branch, and their common ancestor. In our previous example, <code>main</code>, <code>paul_branch</code>, and the merge commit (with "Commit 3" and "Commit 4" as parents), respectively.</p>
<p>This is unlike, say, the fast-forward examples we saw before. The fast-forward examples are actually a case of a two-way merge, as Git only compares two states - for example, where <code>main</code> pointed to, and where <code>john_branch</code> pointed to.</p>
<h3 id="heading-moving-on">Moving on</h3>
<p>Still, this was a simple case of a 3-way merge. John and Paul created different songs, so each of them touched a different file. It was pretty straightforward to execute the merge.</p>
<p>What about more interesting cases?</p>
<p>Let's assume that now John and Paul are co-authoring a new song.</p>
<p>So, John checked out <code>main</code> branch and started writing the song:</p>
<pre><code class="lang-bash">git checkout main
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/a_day_in_the_life_md.png" alt="John's new song" width="600" height="400" loading="lazy">
<em>John's new song</em></p>
<p>He staged and committed it ("Commit 7"):</p>
<pre><code class="lang-bash">git add a_day_in_the_life.md
git commit -m <span class="hljs-string">"Commit 7"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_7.png" alt="John's new song is committed" width="600" height="400" loading="lazy">
<em>John's new song is committed</em></p>
<p>Now, Paul branches:</p>
<pre><code class="lang-bash">git checkout -b paul_branch_2
</code></pre>
<p>And edits the song, adding another verse:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/a_day_in_the_life_paul_verse.png" alt="Paul added a new verse" width="600" height="400" loading="lazy">
<em>Paul added a new verse</em></p>
<p>Of course, the original song does not include the title "Paul's Verse", but I added it here for clarity.</p>
<p>Paul stages and commits the changes:</p>
<pre><code class="lang-bash">git add a_day_in_the_life.md
git commit -m <span class="hljs-string">"Commit 8"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_8.png" alt="The history after introducing &quot;Commit 8&quot;" width="600" height="400" loading="lazy">
<em>The history after introducing "Commit 8"</em></p>
<p>John also branches out from main and adds an additional two lines at the end:</p>
<pre><code class="lang-bash">git checkout main
git checkout -b john_branch_2
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/a_day_in_the_life_john_addition.png" alt="John added the two last lines" width="600" height="400" loading="lazy">
<em>John added the two last lines</em></p>
<p>John stages and commits his changes too ("Commit 9"):</p>
<pre><code class="lang-bash">git add a_day_in_the_life.md
git commit -m <span class="hljs-string">"Commit 9"</span>
</code></pre>
<p>This is the resulting history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_9.png" alt="The history after John's last commit" width="600" height="400" loading="lazy">
<em>The history after John's last commit</em></p>
<p>So, both Paul and John modified the same file on different branches. Will Git be successful in merging them?</p>
<p>Say now we don't go through <code>main</code>, but John will try to merge Paul's new branch into his branch:</p>
<pre><code class="lang-bash">git merge paul_branch_2
</code></pre>
<p>Wait! Don't run this command! Why would you let Git do all the hard work? You are trying to understand the process here.</p>
<p>So, first, Git needs to find the merge base. Can you see which commit that would be?</p>
<p>Correct, it would be the last commit on the <code>main</code> branch, where the two diverged - that is, "Commit 7".</p>
<p>You can verify that by using:</p>
<pre><code class="lang-bash">git merge-base john_branch_2 paul_branch_2
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/merge_base_2.png" alt="&quot;Commit 7&quot; is the merge base" width="600" height="400" loading="lazy">
<em>"Commit 7" is the merge base</em></p>
<p>Checkout the merge base so you can later apply the patches you will create:</p>
<pre><code class="lang-bash">git checkout main
</code></pre>
<p>Great, now Git should compute the diffs and generate the patches. You can observe the diffs directly:</p>
<pre><code class="lang-bash">git diff main paul_branch_2
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_main_paul_branch_2.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git diff main paul_branch_2</code>_</p>
<p>Will applying this patch succeed? Well, no problem, Git has all the context lines in place.</p>
<p>Switch to the merge-base (which is "Commit 7", also referenced by <code>main</code>), and ask Git to apply this patch:</p>
<pre><code class="lang-bash">git checkout main
git diff main paul_branch_2 &gt; paul_branch_2.patch
git apply --index paul_branch_2.patch
</code></pre>
<p>And this worked, no problem at all.</p>
<p>Now, compute the diff between John's new branch and the merge base. Notice that you haven't committed the applied changes, so <code>john_branch_2</code> still points at the same commit as before, "Commit 9":</p>
<pre><code class="lang-bash">git diff main john_branch_2
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_main_john_branch_2.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git diff main john_branch_2</code>_</p>
<p>Will applying this diff work?</p>
<p>Well, indeed, yes. Notice that even though the line numbers have changed on the current version of the file, thanks to the context lines Git is able to locate where it needs to add these lines…</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diff_main_john_branch_2_context.png" alt="Git can rely on the context lines" width="600" height="400" loading="lazy">
<em>Git can rely on the context lines</em></p>
<p>Save this patch and apply it then:</p>
<pre><code class="lang-bash">git diff main john_branch_2 &gt; john_branch_2.patch
git apply --index john_branch_2.patch
</code></pre>
<p>Observe the result file:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/a_day_in_the_life_after_merge.png" alt="The result after applying Paul's patch" width="600" height="400" loading="lazy">
<em>The result after applying Paul's patch</em></p>
<p>Cool, exactly what we wanted.</p>
<p>You can now create the tree and relevant commit:</p>
<pre><code class="lang-bash">git write-tree
</code></pre>
<p>Don't forget to specify both parents:</p>
<pre><code class="lang-bash">git commit-tree &lt;TREE-ID&gt; -p paul_branch_2 -p john_branch_2 -m <span class="hljs-string">"Merging new changes"</span>
</code></pre>
<p>See how I used the branch names here? After all, they are just pointers to the commits we want.</p>
<p>Cool, look at the log from the new commit:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_lol_merging_new_changes.png" alt=" after creating the merge commit" width="600" height="400" loading="lazy">
_<code>git lol &amp;lt;SHA_OF_THE_MERGE_COMMIT&amp;gt;</code> after creating the merge commit_</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_merging_new_changes_commit.png" alt="The history after creating the merge commit" width="600" height="400" loading="lazy">
<em>The history after creating the merge commit</em></p>
<p>Exactly what we wanted.</p>
<p>You can also let Git perform the job for you. You can checkout <code>john_branch_2</code>, which you haven't moved - so it still points to the same commit as it did before the merge. So all you need to do is run:</p>
<pre><code class="lang-bash">git checkout john_branch_2
git merge paul_branch_2
</code></pre>
<p>Observe the resulting history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/merge_branches_2.png" alt=" after letting Git perform the merge" width="600" height="400" loading="lazy">
<em><code>git lol</code> after letting Git perform the merge</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_merging_with_git.png" alt="A visualization of the history after letting Git perform the merge" width="600" height="400" loading="lazy">
<em>A visualization of the history after letting Git perform the merge</em></p>
<p>Just as before, you have a merge commit pointing to "Commit 8" and "Commit 9" as its parents. "Commit 9" is the first parent since you merged into it.</p>
<p>But this was still quite simple… John and Paul worked on the same file, but on very different parts. You could also directly apply Paul's changes to John's branch. If you go back to John's branch before the merge:</p>
<pre><code class="lang-bash">git reset --hard HEAD~
</code></pre>
<p>And now apply Paul's changes:</p>
<pre><code class="lang-bash">git apply --index paul_branch_2.patch
</code></pre>
<p>You will get the same result.</p>
<p>But what happens when the two branches include changes on the same files, in the same locations?</p>
<h3 id="heading-more-advanced-git-merge-cases">More Advanced Git Merge Cases</h3>
<p>What would happen if John and Paul were to coordinate a new song, and work on it together?</p>
<p>In this case, John creates the first version of this song in the main branch:</p>
<pre><code class="lang-bash">git checkout main
nano everyone.md
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/everyone_1.png" alt="The contents of  prior to the first commit" width="600" height="400" loading="lazy">
<em>The contents of <code>everyone.md</code> prior to the first commit</em></p>
<p>By the way, this text is indeed taken from the version that John Lennon recorded for a demo in 1968. But this isn't a book about the Beatles. If you're curious about the process the Beatles underwent while writing this song, you can follow the links in the end of this chapter.</p>
<pre><code class="lang-bash">git add everyone.md
git commit -m <span class="hljs-string">"Commit 10"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_commit_10.png" alt="Introducing &quot;Commit 10&quot;" width="600" height="400" loading="lazy">
<em>Introducing "Commit 10"</em></p>
<p>Now John and Paul split. Paul creates a new verse in the beginning:</p>
<pre><code class="lang-bash">git checkout -b paul_branch_3
nano everyone.md
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/everyone_2.png" alt="Paul added a new verse in the beginning" width="600" height="400" loading="lazy">
<em>Paul added a new verse in the beginning</em></p>
<p>Also, while talking to John, they decided to change the word "feet" to "foot", so Paul adds this change as well.</p>
<p>And Paul adds and commits his changes to the repo:</p>
<pre><code class="lang-bash">git add everyone.md
git commit -m <span class="hljs-string">"Commit 11"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_11.png" alt="The history after introducing &quot;Commit 11&quot;" width="600" height="400" loading="lazy">
<em>The history after introducing "Commit 11"</em></p>
<p>You can observe Paul's changes, by comparing this branch's state to the state of branch <code>main</code>:</p>
<pre><code class="lang-bash">git diff main
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main.png" alt="The output of  from Paul's branch" width="600" height="400" loading="lazy">
<em>The output of <code>git diff main</code> from Paul's branch</em></p>
<p>Store this diff in a patch file:</p>
<pre><code class="lang-bash">git diff main &gt; paul_3.patch
</code></pre>
<p>Now back to <code>main</code>…</p>
<pre><code class="lang-bash">git checkout main
</code></pre>
<p>John decides to make another change, in his own new branch:</p>
<pre><code class="lang-bash">git checkout -b john_branch_3
</code></pre>
<p>And he replaces the line "Everyone had the boot in" with the line "Everyone had a wet dream". In addition, John changed the word "feet" to "foot", following his talk with Paul.</p>
<p>Observe the diff:</p>
<pre><code class="lang-bash">git diff main
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main_2.png" alt="The output of  from John's branch" width="600" height="400" loading="lazy">
<em>The output of <code>git diff main</code> from John's branch</em></p>
<p>Store this output as well:</p>
<pre><code class="lang-bash">git diff main &gt; john_3.patch
</code></pre>
<p>Now, stage and commit:</p>
<pre><code class="lang-bash">git add everyone.md
git commit -m <span class="hljs-string">"Commit 12"</span>
</code></pre>
<p>This should be your current history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_12.png" alt="The history after introducing &quot;Commit 12&quot;" width="600" height="400" loading="lazy">
<em>The history after introducing "Commit 12"</em></p>
<p>Note that I deleted <code>john_branch_2</code> and <code>paul_branch_2</code> for simplicity. Of course, you can erase them from Git by using <code>git branch -D &lt;branch_name&gt;</code>. As a result, these branch names will not appear in the output of <code>git log</code> or other similar commands.</p>
<p>This also applies to commits that are no longer reachable from any named reference, such as "Commit 8" or "Commit 9". Since they are not reachable from any named reference via the parents' chain, they will not be included in the output of commands such as <code>git log</code>.</p>
<p>Back to our story - Paul told John he had added a new verse, so John would like to merge Paul's changes.</p>
<p>Can John simply apply Paul's patch?</p>
<p>Consider the patch again:</p>
<pre><code class="lang-bash">git diff main paul_branch_3
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main-1.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git diff main paul_branch_3</code>_</p>
<p>As you can see, this diff relies on the line "Everyone had the boot in", but this line no longer exists on John's branch. As a result, you could expect applying the patch to fail. Go on, give it a try:</p>
<pre><code class="lang-bash">git apply paul_3.patch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_apply_paul_3.png" alt="Applying the patch failed" width="600" height="400" loading="lazy">
<em>Applying the patch failed</em></p>
<p>Indeed, you can see that it failed.</p>
<p>But should it really fail?</p>
<p>As explained earlier, <code>git merge</code> uses a 3-way merge algorithm, and this can come in handy here. What would be the first step of this algorithm?</p>
<p>Well, first, Git would find the merge base - that is, the common ancestor of Paul's branch and John's branch. Consider the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_12-1.png" alt="The history after introducing &quot;Commit 12&quot;" width="600" height="400" loading="lazy">
<em>The history after introducing "Commit 12"</em></p>
<p>So the common ancestor of "Commit 11" and "Commit 12" is "Commit 10". You can verify this by running the command:</p>
<pre><code class="lang-bash">git merge-base john_branch_3 paul_branch_3
</code></pre>
<p>Now we can take the patches we generated from the diffs on both branches, and apply them to <code>main</code>. Would that work?</p>
<p>First, try to apply John's patch, and then Paul's patch.</p>
<p>Consider the diff:</p>
<pre><code class="lang-bash">git diff main john_branch_3
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main_2-1.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git diff main john_branch_3</code>_</p>
<p>We can store it in a file:</p>
<pre><code class="lang-bash">git diff main john_branch_3 &gt; john_3.patch
</code></pre>
<p>And apply this patch on main:</p>
<pre><code class="lang-bash">git checkout main
git apply john_3.patch
</code></pre>
<p>Let's consider the result:</p>
<pre><code class="lang-bash">nano everyone.md
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/everyone_3.png" alt="The contents of  after applying John's patch" width="600" height="400" loading="lazy">
<em>The contents of <code>everyone.md</code> after applying John's patch</em></p>
<p>The line changed as expected. Nice 😎</p>
<p>Now, can Git apply Paul's patch? To remind you, this is the patch:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main-2.png" alt="The contents of Paul's patch" width="600" height="400" loading="lazy">
<em>The contents of Paul's patch</em></p>
<p>Well, Git cannot apply this patch, because this patch assumes that the line "Everyone had the boot in" exists. Trying to apply it is liable to fail:</p>
<pre><code class="lang-bash">git apply -v paul_3.branch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_apply_v_paul_3.png" alt="Applying Paul's patch failed" width="600" height="400" loading="lazy">
<em>Applying Paul's patch failed</em></p>
<p>What you tried to do now, applying Paul's patch on the <code>main</code> branch after applying John's patch, is the same as being on <code>john_branch_3</code>, and attempting to apply the patch. That is, running:</p>
<pre><code class="lang-bash">git apply paul_3.patch
</code></pre>
<p>What would happen if we tried the other way around?</p>
<p>First, clean up the state:</p>
<pre><code class="lang-bash">git reset --hard
</code></pre>
<p>And start from Paul's branch:</p>
<pre><code class="lang-bash">git checkout paul_branch_3
</code></pre>
<p>Can we apply John's patch? As a reminder, this is the status of <code>everyone.md</code> on this branch:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/everyone_2-1.png" alt="The contents of  on " width="600" height="400" loading="lazy">
_The contents of <code>everyone.md</code> on <code>paul_branch_3</code>_</p>
<p>And this is John's patch:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main_2-2.png" alt="The contents of John's patch" width="600" height="400" loading="lazy">
<em>The contents of John's patch</em></p>
<p>Would applying John's patch work?</p>
<p>Try to answer yourself before reading on.</p>
<p>You can try:</p>
<pre><code class="lang-bash">git apply john_3.patch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_apply_3_john_3.png" alt="Git fails to apply John's patch" width="600" height="400" loading="lazy">
<em>Git fails to apply John's patch</em></p>
<p>Well, no! Again, if you are not sure what happened, you can always ask <code>git apply</code> to be a bit more verbose:</p>
<pre><code class="lang-bash">git apply -v john_3.patch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_apply_v_john_3.png" alt="You can get more information by using the  flag" width="600" height="400" loading="lazy">
<em>You can get more information by using the <code>-v</code> flag</em></p>
<p>Git is looking for "Everyone put the feet down", but Paul has already changed this line so it now consists of the word "foot" instead of "feet". As a result, applying this patch fails.</p>
<p>Notice that changing the number of context lines here (that is, using <code>git apply</code> with the <code>-C</code> flag, as discussed in the <a class="post-section-overview" href="#heading-chapter-6-diffs-and-patches">previous chapter</a>) is irrelevant - Git is unable to locate the actual line that the patch is trying to erase.</p>
<p>But actually, Git can make this work, if you just add a flag to apply, telling it to perform a 3-way merge under the hood:</p>
<pre><code class="lang-bash">git apply -3 john_3.patch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_apply_3_john_3-1.png" alt="Applying with  flag succeeds" width="600" height="400" loading="lazy">
<em>Applying with <code>-3</code> flag succeeds</em></p>
<p>And consider the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/everyone_4.png" alt="The contents of  after the merge" width="600" height="400" loading="lazy">
<em>The contents of <code>everyone.md</code> after the merge</em></p>
<p>Exactly what we wanted! You have Paul's verse, and both of John's changes!</p>
<p>So, how was Git able to accomplish that?</p>
<p>Well, as I mentioned, Git really did a <strong>3-way merge</strong>, and with this example, it will be a good time to dive into what this actually means.</p>
<h3 id="heading-how-gits-3-way-merge-algorithm-works">How Git's 3-way Merge Algorithm Works</h3>
<p>Get back to the state before applying this patch:</p>
<pre><code class="lang-bash">git reset --hard
</code></pre>
<p>You have now three versions: the merge base, which is "Commit 10", Paul's branch, and John's branch. In general terms, we can say these are the <code>merge base</code>, <code>commit A</code> and <code>commit B</code>. Notice that the <code>merge base</code> is by definition an ancestor of both <code>commit A</code> and <code>commit B</code>.</p>
<p>To perform the merge, Git looks at the diff between the three different versions of the file in question on these three revisions. In your case, it's the file everyone.md, and the revisions are "Commit 10", Paul's branch - that is, "Commit 11", and John's branch, that is, "Commit 12".</p>
<p>Git makes the merging decision based on the status of each line in each of these versions.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_versions.png" alt="The three versions considered for the 3-way merge" width="600" height="400" loading="lazy">
<em>The three versions considered for the 3-way merge</em></p>
<p>In case not all three versions match, that is a conflict. Git can resolve many of these conflicts automatically, as we will now see.</p>
<p>Let's consider specific lines.</p>
<p>The first lines here exist only on Paul's branch:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_versions_1.png" alt="Lines that appear on Paul's branch only" width="600" height="400" loading="lazy">
<em>Lines that appear on Paul's branch only</em></p>
<p>This means that the state of John's branch is equal to the state of the merge base. So the 3-way merge goes with Paul's version.</p>
<p>In general, if the state of the merge base is the same as <code>A</code>, the algorithm goes with <code>B</code>. The reason is that since the merge base is the ancestor of both <code>A</code> and <code>B</code>, Git assumes that this line hasn't changed in <code>A</code>, and it <em>has</em> changed in <code>B</code>, which is the most recent version for that line, and should thus be taken into account.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_way_merge_1.png" alt="If the state of the merge base is the same as , and this state is different from , the algorithm goes with " width="600" height="400" loading="lazy">
<em>If the state of the merge base is the same as <code>A</code>, and this state is different from <code>B</code>, the algorithm goes with <code>B</code></em></p>
<p>Next, you can see lines where all three versions agree - they exist on the merge base, <code>A</code> and <code>B</code>, with equal data.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_versions_2.png" alt="Lines where all three versions agree" width="600" height="400" loading="lazy">
<em>Lines where all three versions agree</em></p>
<p>In this case the algorithm has a trivial choice - just take that version.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_way_merge_2.png" alt="In case all three versions agree, the algorithm goes with that single version" width="600" height="400" loading="lazy">
<em>In case all three versions agree, the algorithm goes with that single version</em></p>
<p>In a previous example, we saw that if the merge base and <code>A</code> agree, and <code>B</code>'s version is different, the algorithm picks <code>B</code>. This works in the other direction too - for example, here you have a line that exists on John's branch, different than that on the merge base and Paul's branch.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_versions_3.png" alt="A line where Paul's version matches the merge base's version, and John has a different version" width="600" height="400" loading="lazy">
<em>A line where Paul's version matches the merge base's version, and John has a different version</em></p>
<p>Hence, John's version is chosen.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_way_merge_3.png" alt="If the state of the merge base is the same as , and this state is different from , the algorithm goes with " width="600" height="400" loading="lazy">
<em>If the state of the merge base is the same as <code>B</code>, and this state is different from <code>A</code>, the algorithm goes with <code>A</code></em></p>
<p>Now consider another case, where both <code>A</code> and <code>B</code> agree on a line, but the value they agree upon is different from the merge base: both John and Paul agreed to change the line "Everyone put their feet down" to "Everyone put their foot down":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_versions_4.png" alt="A line where Paul's version matches John's version; yet the merge base has a different version" width="600" height="400" loading="lazy">
<em>A line where Paul's version matches John's version, yet the merge base has a different version</em></p>
<p>In this case, the algorithm picks the version on both <code>A</code> and <code>B</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_way_merge_4.png" alt="In case A and B agree on a version which is different from the merge base's version, the algorithm picks the version on both A and B" width="600" height="400" loading="lazy">
<em>In case <code>A</code> and <code>B</code> agree on a version which is different from the merge base's version, the algorithm picks the version on both <code>A</code> and <code>B</code></em></p>
<p>Notice this is not a democratic vote. In the previous case, the algorithm picked the minority version, as it resembled the newest version of this line. In this case, it happens to pick the majority - but only because <code>A</code> and <code>B</code> are the revisions that agree on the new version.</p>
<p>The same would happen if we used <code>git merge</code>:</p>
<pre><code class="lang-bash">git merge john_branch_3
</code></pre>
<p>Without specifying any flags, <code>git merge</code> will default to using a <code>3-way merge</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_merge_default.png" alt="By default,  uses a 3-way merge algorithm" width="600" height="400" loading="lazy">
<em>By default, <code>git merge</code> uses a 3-way merge algorithm</em></p>
<p>The status of <code>everyone.md</code> after running <code>git merge john_branch</code> would be the same as the result you achieved by applying the patches with <code>git apply -3</code>.</p>
<p>If you consider the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_merge.png" alt="Git's history after performing the merge" width="600" height="400" loading="lazy">
<em>Git's history after performing the merge</em></p>
<p>You will see that the merge commit indeed has two parents: the first is "Commit 11", that is, where <code>paul_branch_3</code> pointed to before the merge. The second is "Commit 12", where <code>john_branch_3</code> pointed to, and still points to now.</p>
<p>What will happen if you now merge from <code>main</code>? That is, switch to the <code>main</code> branch, which is pointing to "Commit 10":</p>
<pre><code class="lang-bash">git checkout main
</code></pre>
<p>And then merge Paul's branch?</p>
<pre><code class="lang-bash">git merge paul_branch_3
</code></pre>
<p>Indeed, we get a fast-forward merge - as before running this command, <code>main</code> was an ancestor of <code>paul_branch_3</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/fast_forward_merge.png" alt="A fast-forward merge" width="600" height="400" loading="lazy">
<em>A fast-forward merge</em></p>
<p>So, this is a 3-way merge. In general, if all versions agree on a line, then this line is used. If <code>A</code> and the merge base match, and <code>B</code> has another version, <code>B</code> is taken. In the opposite case, where the merge base and <code>B</code> match, the <code>A</code> version is selected. If <code>A</code> and <code>B</code> match, this version is taken, whether the merge base agrees or not.</p>
<p>This description leaves one open question though: What happens in cases where all three versions disagree?</p>
<p>Well, that's a conflict that Git does not resolve automatically. In these cases, Git calls for a human's help.</p>
<h3 id="heading-how-to-resolve-merge-conflicts">How to Resolve Merge Conflicts</h3>
<p>By following so far, you should understand the basics of the command <code>git merge</code>, and how Git can automatically resolve some conflicts. You also understand what cases are automatically resolved.</p>
<p>Next, let's consider a more advanced case.</p>
<p>Say Paul and John keep working on this song.</p>
<p>Paul creates a new branch:</p>
<pre><code class="lang-bash">git checkout -b paul_branch_4
</code></pre>
<p>And he decides to add some "Yeah"s to the song, so he changes this verse as follows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/paul_branch_4_additions.png" alt="Paul's additions" width="600" height="400" loading="lazy">
<em>Paul's additions</em></p>
<p>So Paul stages and commits these changes:</p>
<pre><code class="lang-bash">git add everyone.md
git commit -m <span class="hljs-string">"Commit 13"</span>
</code></pre>
<p>Paul also creates another song, <code>let_it_be.md</code> and adds it to the repo:</p>
<pre><code class="lang-bash">git add let_it_be.md
git commit -m <span class="hljs-string">"Commit 14"</span>
</code></pre>
<p>This is the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_14.png" alt="The history after Paul introduced &quot;Commit 14&quot;" width="600" height="400" loading="lazy">
<em>The history after Paul introduced "Commit 14"</em></p>
<p>Going back to <code>main</code>:</p>
<pre><code class="lang-bash">git checkout main
</code></pre>
<p>John also branches out:</p>
<pre><code class="lang-bash">git checkout -b john_branch_4
</code></pre>
<p>And John also works on the song "Everyone had a hard year", later to be called "I've got a feeling" (again, this is not a book about the Beatles, so I won't elaborate on it here. See the additional links if you are curious).</p>
<p>John decides to change all occurrences of "Everyone" to "Everybody":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/everyone_5.png" alt="John changes all occurrences of &quot;Everyone&quot; to &quot;Everybody&quot;" width="600" height="400" loading="lazy">
<em>John changes all occurrences of "Everyone" to "Everybody"</em></p>
<p>He stages and commits this song to the repo:</p>
<pre><code class="lang-bash">git add everyone.md
git commit -m <span class="hljs-string">"Commit 15"</span>
</code></pre>
<p>Nice. Now John also creates another song, <code>across_the_universe.md</code>. He adds it to the repo as well:</p>
<pre><code class="lang-bash">git add across_the_universe.md
git commit -m <span class="hljs-string">"Commit 16"</span>
</code></pre>
<p>Observe the history again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_16.png" alt="The history after John introduced &quot;Commit 16&quot;" width="600" height="400" loading="lazy">
<em>The history after John introduced "Commit 16"</em></p>
<p>You can see that the history diverges from <code>main</code>, to two different branches - <code>paul_branch_4</code>, and <code>john_branch_4</code>.</p>
<p>At this point, John would like to merge the changes introduced by Paul.</p>
<p>What is going to happen here?</p>
<p>Remember the changes introduced by Paul:</p>
<pre><code class="lang-bash">git diff main paul_branch_4
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main_paul_branch_4.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git diff main paul_branch_4</code>_</p>
<p>What do you think? Will merge work?</p>
<p>Try it out:</p>
<pre><code class="lang-bash">git merge paul_branch_4
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/merge_conflict.png" alt="A merge conflict" width="600" height="400" loading="lazy">
<em>A merge conflict</em></p>
<p>We have a conflict!</p>
<p>Git cannot merge these branches on its own. You can get an overview of the merge state, using <code>git status</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_after_merge_failed.png" alt="The output of  right after the merge operation" width="600" height="400" loading="lazy">
<em>The output of <code>git status</code> right after the merge operation</em></p>
<p>The changes that Git had no problem resolving are staged for commit. And there is a separate section for "unmerged paths" - these are files with conflicts that Git could not resolve on its own.</p>
<p>It's time to understand why and when these conflicts happen, how to resolve them, and also how Git handles them under the hood.</p>
<p>Alright then! I hope you are at least as excited as I am. 😇</p>
<p>Let's recall what we know about 3-way merges:</p>
<p>First, Git will look for the merge base - the common ancestor of <code>john_branch_4</code> and <code>paul_branch_4</code>. Which commit would that be?</p>
<p>It would be the tip of the <code>main</code> branch, the commit in which we merged <code>john_branch_3</code> into <code>paul_branch_3</code>.</p>
<p>Again, if you are not sure, you can verify that by running:</p>
<pre><code class="lang-bash">git merge-base john_branch_4 paul_branch_4
</code></pre>
<p>And at the current state, <code>git status</code> knows which files are staged and which aren't.</p>
<p>Consider the process for each <em>file</em>, which is the same as the 3-way merge algorithm we considered per line, but on a file's level:</p>
<p><code>across_the_universe.md</code> exists on John's branch, but doesn't exist on the merge base or on Paul's branch. So Git chooses to include this file. Since you are already on John's branch and this file is included in the tip of this branch, it is not mentioned by <code>git status</code>.</p>
<p><code>let_it_be.md</code> exists on Paul's branch, but doesn't exist on the merge base or John's branch. So <code>git merge</code> "chooses" to include it.</p>
<p>What about <code>everyone.md</code>? Well, here we have three different states of this file: its state on the merge base, its state on John's branch, and its state on Paul's branch. While performing a merge, Git stores all of these versions on the index.</p>
<p>Let's observe that by looking directly at the index with the command <code>git ls-files</code>:</p>
<pre><code class="lang-bash">git ls-files -s --abbrev
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/ls_files_abbrev.png" alt="The output of  after the merge operation" width="600" height="400" loading="lazy">
<em>The output of <code>git ls-files -s --abbrev</code> after the merge operation</em></p>
<p>You can see that <code>everyone.md</code> has three different entries. Git assigns each version a number that represents the "stage" of the file, and this is a distinct property of an index entry, alongside the file's name and the mode bits.</p>
<p>When there is no merge conflict regarding a file, its "stage" is <code>0</code>. This is indeed the state for <code>across_the_universe.md</code>, and for <code>let_it_be.md</code>.</p>
<p>On a conflict's state, we have:</p>
<ul>
<li>Stage <code>1</code> - which is the merge base.</li>
<li>Stage <code>2</code> - which is "your" version. That is, the version of the file on the branch you are merging <em>into</em>. In our example, this would be <code>john_branch_4</code>.</li>
<li>Stage <code>3</code> - which is "their" version, also called the <code>MERGE_HEAD</code>. That is, the version on the branch you are merging (into the current branch). In our example, that is <code>paul_branch_4</code>.</li>
</ul>
<p>To observe the file's contents in a specific stage, you can use a command I introduced in a previous post, git cat-file, and provide the blob's SHA:</p>
<pre><code class="lang-bash">git cat-file -p &lt;BLOB_SHA_FOR_STAGE_2&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cat_file.png" alt="Using -file to present the content of the file on John's branch, right from its state in the index" width="600" height="400" loading="lazy">
<em>Using <code>git cat-file</code> to present the content of the file on John's branch, right from its state in the index</em></p>
<p>And indeed, this is the content we expected - from John's branch, where the lines start with "Everybody" rather than "Everyone".</p>
<p>A nice trick that allows you to see the content quickly without providing the blob's SHA-1 value, is by using <code>git show</code>, like so:</p>
<pre><code class="lang-bash">git show :&lt;STAGE&gt;:everyone.md
</code></pre>
<p>For example, to get the content of the same version as with git cat-file -p , you can write <code>git show :2:everyone.md</code>.</p>
<p>Git records the three states of the three commits into the index in this way at the start of the merge. It then follows the three-way merge algorithm to quickly resolve the simple cases:</p>
<p>In case all three stages match, then the selection is trivial.</p>
<p>If one side made a change while the other did nothing - that is, stage <code>1</code> matches stage <code>2</code>- then we choose stage <code>3</code>, or vice versa. That's exactly what happened with <code>let_it_be.md</code> and <code>across_the_universe.md</code>.</p>
<p>In case of a deletion on the incoming branch, for example, and given there were no changes on the current branch, then we would see that stage <code>1</code> matches stage <code>2</code>, but there is no stage <code>3</code>. In this case, <code>git merge</code> removes the file for the merged version.</p>
<p>What's really cool here is that for matching, Git doesn't need the actual files. Rather, it can rely on the SHA-1 values of the corresponding blobs. This way, Git can easily detect the state a file is in.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/3_way_merge_4-1.png" alt="Git performs the same 3-way merge algorithm on a files level" width="600" height="400" loading="lazy">
<em>Git performs the same 3-way merge algorithm on a files level</em></p>
<p>For <code>everyone.md</code> you have this special case - where stage <code>1</code>, stage <code>2</code> and stage <code>3</code> are all different from one another. That is, they have different blob SHAs. It's time to go deeper and understand the merge conflict. 😊</p>
<p>One way to do that would be to simply use <code>git diff</code>. In a <a class="post-section-overview" href="#heading-chapter-6-diffs-and-patches">previous chapter</a>, we examined git diff in detail, and saw that it shows the differences between various combinations of the working tree, index or commits.</p>
<p>But <code>git diff</code> also has a special mode for helping with merge conflicts:</p>
<pre><code class="lang-bash">git diff
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_conflict.png" alt="The output of  during a merge conflict" width="600" height="400" loading="lazy">
<em>The output of <code>git diff</code> during a merge conflict</em></p>
<p>This output may be confusing at first, but once you get used to it, it's pretty clear. Let's start by understanding it, and then see how you can resolve conflicts with other, more visual tools.</p>
<p>The conflicted section is separated by the "equal" marks (<code>====</code>), and marked with the corresponding branches. In this context, "ours" is the current branch. In this example, that would be <code>john_branch_4</code>, the branch that <code>HEAD</code> was pointing to when we initiated the <code>git merge</code> command. "Theirs" is the <code>MERGE_HEAD</code>, the branch that we are merging in - in this case, <code>paul_branch_4</code>.</p>
<p>So <code>git diff</code> without any special flags shows changes between the working tree and the index - which in this case are the conflicts yet to be resolved. The output doesn't include staged changes, which is very convenient for resolving the conflict.</p>
<p>Time to resolve this manually. Fun!</p>
<p>So, why is this a conflict?</p>
<p>For Git, Paul and John made different changes to the same line, for a few lines. John changed it to one thing, and Paul changed it to another thing. Git cannot decide which one is correct.</p>
<p>This is not the case for the last lines, like the line that used to be "Everyone had a hard year" on the merge base. Paul hasn't changed this line, or the lines surrounding it, so its version on paul_branch_4, or "theirs" in our case, agrees with the <code>merge_base</code>. Yet John's version, "ours", is different. Thus <code>git merge</code> can easily decide to take this version.</p>
<p>But what about the conflicted lines?</p>
<p>In this case, I know what I want, and that is actually a combination of these lines. I want the lines to start with "Everybody", following John's change, but also to include Paul's "yeah"s. So go ahead and create the desired version by editing everyone.md:</p>
<pre><code class="lang-bash">nano everyone.md
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/everyone_6.png" alt="Editing the file manually to achieve the desired state" width="600" height="400" loading="lazy">
<em>Editing the file manually to achieve the desired state</em></p>
<p>To compare the result file to what you had in the branch prior to the merge, you can run:</p>
<pre><code class="lang-bash">git diff --ours
</code></pre>
<p>Similarly, if you wish to see how the result of the merge differs from the branch you merged into our branch, you can run:</p>
<pre><code class="lang-bash">git diff --theirs
</code></pre>
<p>You can even see how the result is different from both sides using:</p>
<pre><code class="lang-bash">git diff --base
</code></pre>
<p>Now you can stage the fixed version:</p>
<pre><code class="lang-bash">git add everyone.md
</code></pre>
<p>After staging, if you look at <code>git status</code>, you will see no conflicts:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_after_manual_fix.png" alt="After staging the fixed version , there are no conflicts" width="600" height="400" loading="lazy">
<em>After staging the fixed version <code>everyone.md</code>, there are no conflicts</em></p>
<p>You can now simply use <code>git commit</code>, and Git will present you with a commit message containing details about the merge. You can modify it if you like, or leave it as is. Regardless of the commit message, Git will create a "merge commit" - that is, a commit with more than one parent.</p>
<p>To validate that, consider the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_merge_2.png" alt="The history after completing the merge operation" width="600" height="400" loading="lazy">
<em>The history after completing the merge operation</em></p>
<p><code>john_branch_4</code> now points to the new merge commit. The incoming branch, "theirs", in this case, <code>paul_branch_4</code>, stays where it was.</p>
<h3 id="heading-how-to-use-vs-code-to-resolve-conflicts">How to Use VS Code to Resolve Conflicts</h3>
<p>You will now see how to resolve the same conflict using a graphical tool. For this example, I use VS Code, which is a free and popular code editor. There are many other tools, but the process is similar, so I will just show VS Code as an example.</p>
<p>First, get back to the state before the merge:</p>
<pre><code class="lang-bash">git reset --hard HEAD~
</code></pre>
<p>And try to merge again:</p>
<pre><code class="lang-bash">git merge paul_branch_4
</code></pre>
<p>You should be back at the same status:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_after_merge_failed-1.png" alt="Back at the conflicting status" width="600" height="400" loading="lazy">
<em>Back at the conflicting status</em></p>
<p>Let's see how this appears on VS Code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/vs_code_1.png" alt="Conflict resolution with VS Code" width="600" height="400" loading="lazy">
<em>Conflict resolution with VS Code</em></p>
<p>VS Code marks the different versions with "Current Change" - which is the "ours" version, the current <code>HEAD</code>, and "Incoming Change" for the branch we are merging into the active branch. You can accept one of the changes (or both) by clicking on one of the options.</p>
<p>If you clicked on <code>Resolve in Merge editor</code>, you'll get a more visual view of the state. VS Code shows the status of each line:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/vs_code_2-1.png" alt="VS Code's Merge Editor" width="600" height="400" loading="lazy">
<em>VS Code's Merge Editor</em></p>
<p>If you look closely, you will see that VS Code shows changes within words - for example, showing that "Every<strong>one</strong>" was changed to "Every<strong>body</strong>", marking the changed parts.</p>
<p>You can accept either version, or you can accept a combination. In this case, if you click on "Accept Combination", you get this result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/vs_code_3.png" alt="VS Code's Merge Editor after clicking on &quot;Accept Combination&quot;" width="600" height="400" loading="lazy">
<em>VS Code's Merge Editor after clicking on "Accept Combination"</em></p>
<p>VS Code did a really good job! The same three way merge algorithm was implemented here and used on the <em>word</em> level rather than the <em>line</em> level. So VS Code was able to actually resolve this conflict in a rather impressive way. Of course, you can modify VS Code's suggestion, but it provided a <em>very</em> good start.</p>
<h3 id="heading-one-more-powerful-tool">One More Powerful Tool</h3>
<p>Well, this was the first time in this book that I've used a tool with a graphical user interface. Indeed, graphical interfaces can be convenient to understand what's going on when you are resolving merge conflicts.</p>
<p>However, like in many other cases, when we need to really understand what's going on, the command line becomes handy. So, let's get back to the command line and learn a tool that can come in handy in more complicated cases.</p>
<p>Again, go back to the state before the merge:</p>
<pre><code class="lang-bash">git reset --hard HEAD~
</code></pre>
<p>And merge:</p>
<pre><code class="lang-bash">git merge paul_branch_4
</code></pre>
<p>And say, you are not exactly sure what happened. Why is there a conflict? One very useful command would be:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> -p --merge
</code></pre>
<p>As a reminder, <code>git log</code> shows the history of commits that are reachable from <code>HEAD</code>. Adding <code>-p</code> tells <code>git log</code> to show the commits along with the diffs they introduced. The <code>--merge</code> switch makes the command show all commits containing changes relevant to any unmerged files, on either branch, together with their diffs.</p>
<p>This can help you identify the changes in history that led to the conflicts. So in this example, you'd see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_p_merge.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git log -p --merge</code></em></p>
<p>The first commit we see is "Commit 15", as in this commit John modified everyone.md, a file that still has conflicts. Next, Git shows "Commit 13", where Paul changed <code>everyone.md</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_p_merge_2.png" alt="The output of  - continued" width="600" height="400" loading="lazy">
<em>The output of <code>git log -p --merge</code> - continued</em></p>
<p>Notice that <code>git log --merge</code> did not mention previous commits that changed <code>everyone.md</code> before "Commit 13", as they didn't affect the current conflict.</p>
<p>This way, <code>git log</code> tells you all you need to know to understand the process that got you into the current conflicting state. Cool! 😎</p>
<p>Using the command line, you can also ask Git to take only one side of the changes - either "ours" or "theirs", even for a specific file.</p>
<p>You can also instruct Git to take some parts of the diffs of one file and another from another file. I will provide links that describe how to do that in <a class="post-section-overview" href="#heading-diffs-and-patches">the additional resources of this chapter in the appendix</a>.</p>
<p>For the most part, you can accomplish that pretty easily, either manually or from the UI of your favorite IDE.</p>
<p>For now, it's time for a recap.</p>
<h3 id="heading-recap-understanding-git-merge">Recap - Understanding Git Merge</h3>
<p>In this chapter, you got an extensive overview of merging with Git. You learned that merging is the process of combining the recent changes from several branches into a single new commit. The new commit has two parents - those commits which had been the tips of the branches that were merged.</p>
<p>We considered a simple, fast-forward merge, which is possible when one branch diverged from the base branch, and then just added commits on top of the base branch.</p>
<p>We then considered three-way merges, and explained the three-stage process:</p>
<ul>
<li>First, Git locates the merge base. As a reminder, this is the first commit that is reachable from both branches.</li>
<li>Second, Git calculates two diffs - one diff from the merge base to the <em>first</em> branch, and another diff from the merge base to the <em>second</em> branch. Git generates patches based on those diffs.</li>
<li>Third and last, Git applies both patches to the merge base using a 3-way merge algorithm. The result is the state of the new merge commit.</li>
</ul>
<p>We dove deeper into the process of a 3-way merge, whether at a file level or a hunk level. We considered when Git is able to rely on a 3-way merge to automatically resolve conflicts, and when it just can't.</p>
<p>You saw the output of <code>git diff</code> when we are in a conflicting state, and how to resolve conflicts either manually or with VS Code.</p>
<p>There is much more to be said about merges - different merge strategies, recursive merges, and so on. Yet, I believe this chapter covered everything needed so you have a robust understanding of what merge is, and what happens under the hood in the vast majority of cases.</p>
<h3 id="heading-beatles-related-resources">Beatles-Related Resources</h3>
<ul>
<li><a target="_blank" href="https://www.the-paulmccartney-project.com/song/ive-got-a-feeling/">https://www.the-paulmccartney-project.com/song/ive-got-a-feeling/</a></li>
<li><a target="_blank" href="https://www.cheatsheet.com/entertainment/did-john-lennon-or-paul-mccartney-write-the-classic-a-day-in-the-life.html/">https://www.cheatsheet.com/entertainment/did-john-lennon-or-paul-mccartney-write-the-classic-a-day-in-the-life.html/</a></li>
<li><a target="_blank" href="http://lifeofthebeatles.blogspot.com/2009/06/ive-got-feeling-lyrics.html">http://lifeofthebeatles.blogspot.com/2009/06/ive-got-feeling-lyrics.html</a></li>
</ul>
<h2 id="heading-chapter-8-understanding-git-rebase">Chapter 8 - Understanding Git Rebase</h2>
<p>One of the most powerful tools a developer can have in their toolbox is <code>git rebase</code>. Yet it is notorious for being complex and misunderstood.</p>
<p>The truth is, if you understand what it actually does, <code>git rebase</code> is a very elegant, and straightforward tool to achieve so many different things in Git.</p>
<p>In the previous chapters in this part, you learned what Git diffs are, what a merge is, and how Git resolves merge conflicts. In this chapter, you will understand what Git rebase is, why it's different from merge, and how to rebase with confidence.</p>
<h3 id="heading-short-recap-what-is-git-merge">Short Recap - What is Git Merge?</h3>
<p>Under the hood, <code>git rebase</code> and <code>git merge</code> are very, very different things. Then why do people compare them all the time?</p>
<p>The reason is their usage. When working with Git, we usually work in different branches and introduce changes to those branches.</p>
<p>In the previous chapter, we considered the example where John and Paul (of the Beatles) were co-authoring a new song. They started from the <code>main</code> branch, and then each diverged, modified the lyrics, and committed their changes.</p>
<p>Then, the two wanted to <em>integrate</em> their changes, which is something that happens very frequently when working with Git.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diverging_history_commit_9.png" alt="A diverging history -  and  diverged from " width="600" height="400" loading="lazy">
_A diverging history - <code>paul_branch</code> and <code>john_branch</code> diverged from <code>main</code>_</p>
<p>There are two main ways to integrate changes introduced in different branches in Git, or in other words, different commits and commit histories. These are merge and rebase.</p>
<p>In the previous chapter, we got to know <code>git merge</code> pretty well. We saw that when performing a merge, we create a <strong>merge commit</strong> - where the contents of this commit are a combination of the two branches, and it also has two parents, one in each branch.</p>
<p>So, say you are on the branch <code>john_branch</code> (assuming the history depicted in the drawing above), and you run <code>git merge paul_branch</code>. You will get to this state - where on <code>john_branch</code>, there is a new commit with two parents. The first one will be the commit on the <code>john_branch</code> branch where <code>HEAD</code> was pointing to a state before performing the merge - in this case, "Commit 6". The second will be the commit pointed to by <code>paul_branch</code>, "Commit 9".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_merge_paul_branch.png" alt="The result of running : a new Merge Commit with two parents" width="600" height="400" loading="lazy">
_The result of running <code>git merge paul_branch</code>: a new Merge Commit with two parents_</p>
<p>Look again at the history graph: you created a <strong>diverged</strong> history. You can actually see where it branched and where it merged again.</p>
<p>So when using <code>git merge</code>, you do not rewrite history - but rather, you add a commit to the existing history. And specifically, a commit that creates a diverged history.</p>
<h3 id="heading-how-is-git-rebase-different-than-git-merge">How is <code>git rebase</code> Different than <code>git merge</code>?</h3>
<p>When using <code>git rebase</code>, something different happens.</p>
<p>Let's start with the big picture: if you are on <code>paul_branch</code>, and use <code>git rebase john_branch</code>, Git goes to the common ancestor of John's branch and Paul's branch. Then it takes the patches introduced in the commits on Paul's branch, and applies those changes to John's branch.</p>
<p>So here, you use <code>rebase</code> to take the changes that were committed on one branch - Paul's branch - and replay them on a different branch, <code>john_branch</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_rebase_john_branch.png" alt="The result of running : the commits on  were &quot;replayed&quot; on top of " width="600" height="400" loading="lazy">
_The result of running <code>git rebase john_branch</code>: the commits on <code>paul_branch</code> were "replayed" on top of <code>john_branch</code>_</p>
<p>Wait, what does that mean?</p>
<p>We will now take this bit by bit to make sure you fully understand what's happening under the hood 😎</p>
<h3 id="heading-cherry-pick-as-a-basis-for-rebase"><code>cherry-pick</code> as a Basis for Rebase</h3>
<p>It is useful to think of rebase as performing <code>git cherry-pick</code> - a command that takes a commit, computes the patch this commit introduces by computing the difference between the parent's commit and the commit itself, and then cherry-pick "replays" this difference.</p>
<p>Let's do this manually.</p>
<p>If we look at the difference introduced by "Commit 5" by performing <code>git diff main &lt;SHA_OF_COMMIT_5&gt;</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main_commit_5.png" alt="Running  to observe the patch introduced by &quot;Commit 5&quot;" width="600" height="400" loading="lazy">
<em>Running <code>git diff</code> to observe the patch introduced by "Commit 5"</em></p>
<p>As always, you are encouraged to run the commands yourself while reading this chapter. Unless noted otherwise, I will use the following repository:</p>
<p><a target="_blank" href="https://github.com/Omerr/rebase_playground.git">https://github.com/Omerr/rebase_playground.git</a></p>
<p>I recommend you clone it locally and have the same starting point I am using for this chapter.</p>
<p>You can see that in this commit, John started working on a song called "Lucy in the Sky with Diamonds":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main_commit_5_output.png" alt="The output of  - the patch introduced by &quot;Commit 5&quot;" width="600" height="400" loading="lazy">
<em>The output of <code>git diff</code> - the patch introduced by "Commit 5"</em></p>
<p>As a reminder, you can also use the command <code>git show</code> to get the same output:</p>
<pre><code class="lang-bash">git show &lt;SHA_OF_COMMIT_5&gt;
</code></pre>
<p>Now, if you <code>cherry-pick</code> this commit, you will introduce <em>this change</em> specifically, on the active branch. Switch to <code>main</code> first:</p>
<pre><code class="lang-bash">git checkout main (or git switch main)
</code></pre>
<p>And create another branch:</p>
<pre><code class="lang-bash">git checkout -b my_branch (or git switch -c my_branch)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_my_branch.png" alt="Creating  that branches from " width="600" height="400" loading="lazy">
_Creating <code>my_branch</code> that branches from <code>main</code>_</p>
<p>Next, <code>cherry-pick</code> "Commit 5":</p>
<pre><code class="lang-bash">git cherry-pick &lt;SHA_OF_COMMIT_5&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cherry_pick_commit_5.png" alt="Using  to apply the changes introduced in &quot;Commit 5&quot; onto " width="600" height="400" loading="lazy">
<em>Using <code>cherry-pick</code> to apply the changes introduced in "Commit 5" onto <code>main</code></em></p>
<p>Consider the log (output of <code>git lol</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_lol_commit_5.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git lol</code></em></p>
<p>It seems like you <em>copy-pasted</em> "Commit 5". Remember that even though it has the same commit message, and introduces the same changes, and even points to the same tree object as the original "Commit 5" in this case - it is still a different commit object, as it was created with a different timestamp.</p>
<p>Looking at the changes, using <code>git show HEAD</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_show_HEAD-1.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git show HEAD</code></em></p>
<p>They are the same as "Commit 5"'s.</p>
<p>And of course, if you look at the file (say, by using <code>nano lucy_in_the_sky_with_diamonds.md</code>), it will be in the same state as it has been after the original "Commit 5".</p>
<p>Cool! 😎</p>
<p>You can now remove the new branch so it doesn't appear on your history every time:</p>
<pre><code class="lang-bash">git checkout main
git branch -D my_branch
</code></pre>
<h3 id="heading-beyond-cherry-pick-how-to-use-git-rebase">Beyond <code>cherry-pick</code> - How to Use <code>git rebase</code></h3>
<p>You can view <code>git rebase</code> as a way to perform multiple <code>cherry-pick</code>s one after the other - that is, to "replay" multiple commits. This is not the only thing you can do with rebase, but it's a good starting point for our explanation.</p>
<p>It's time to play with <code>git rebase</code>!</p>
<p>Before, you merged <code>paul_branch</code> into <code>john_branch</code>. What would happen if you <em>rebased</em> <code>paul_branch</code> on top of <code>john_branch</code>? You would get a very different history.</p>
<p>In essence, it would seem as if we took the changes introduced in the commits on <code>paul_branch</code>, and replayed them on <code>john_branch</code>. The result would be a linear history.</p>
<p>To understand the process, I will provide the high level view, and then dive deeper into each step. The process of rebasing one branch on top of another branch is as follows:</p>
<ol>
<li>Find the common ancestor.</li>
<li>Identify the commits to be "replayed".</li>
<li>For every commit <code>X</code>, compute <code>diff(parent(X), X)</code>, and store it as a <code>patch(X)</code>.</li>
<li>Move <code>HEAD</code> to the new base.</li>
<li>Apply the generated patches in order on the target branch. Each time, create a new commit object with the new state.</li>
</ol>
<p>The process of making new commits with the same change sets as existing ones is also called "<strong>replaying</strong>" those commits, a term we have already used.</p>
<h3 id="heading-time-to-get-hands-on-with-rebase">Time to Get Hands-On with Rebase</h3>
<p>Before running the following command command, make sure you have <code>john_branch</code> locally, so run:</p>
<pre><code class="lang-bash">git checkout john_branch
</code></pre>
<p>Start from Paul's branch:</p>
<pre><code class="lang-bash">git checkout paul_branch
</code></pre>
<p>This is the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/diverging_history_commit_9-1.png" alt="Commit history before performing " width="600" height="400" loading="lazy">
<em>Commit history before performing <code>git rebase</code></em></p>
<p>And now, to the exciting part:</p>
<pre><code class="lang-bash">git rebase john_branch
</code></pre>
<p>And observe the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_rebase.png" alt="The history after rebasing" width="600" height="400" loading="lazy">
<em>The history after rebasing</em></p>
<p>With <code>git merge</code> you added to the history, while with <code>git rebase</code> you <strong>rewrite history</strong>. You create <strong>new</strong> commit objects. In addition, the result is a linear history graph - rather than a diverging graph.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_rebase_2.png" alt="The history after rebasing" width="600" height="400" loading="lazy">
<em>The history after rebasing</em></p>
<p>In essence, you "copied" the commits that were on <code>paul_branch</code> and that were introduced after "Commit 4", and "pasted" them on top of <code>john_branch</code>.</p>
<p>The command is called "rebase", because it changes the base commit of the branch it's run from. That is, in your case, before running <code>git rebase</code>, the base of <code>paul_branch</code> was "Commit 4" - as this is where the branch was "born" (from <code>main</code>). With <code>rebase</code>, you asked Git to give it another base - that is, pretend as if it had been born from "Commit 6".</p>
<p>To do that, Git took what used to be "Commit 7", and "replayed" the changes introduced in this commit onto "Commit 6". Then it created a new commit object. This object differs from the original "Commit 7" in three aspects:</p>
<ol>
<li>It has a different timestamp.</li>
<li>It has a different parent commit - "Commit 6", rather than "Commit 4".</li>
<li>The tree object it is pointing to is different - as the changes were introduced to the tree pointed to by "Commit 6", and not the tree pointed to by "Commit 4".</li>
</ol>
<p>Notice the last commit here, "Commit 9'". The snapshot it represents (that is, the tree that it points to) is exactly the same tree you would get by merging the two branches. The state of the files in your Git repository would be <strong>the same</strong> as if you used <code>git merge</code>. It's only the <em>history</em> that is different, and the commit objects of course.</p>
<p>Now, you can simply use:</p>
<pre><code class="lang-bash">git checkout main
git merge paul_branch
</code></pre>
<p>Hm.... What would happen if you ran this last command? Consider the commit history again, after checking out <code>main</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_checkout_main.png" alt="The history after rebasing and checking out " width="600" height="400" loading="lazy">
<em>The history after rebasing and checking out <code>main</code></em></p>
<p>What would it mean to merge <code>main</code> and <code>paul_branch</code>?</p>
<p>Indeed, Git can simply perform a fast-forward merge, as the history is completely linear (if you need a reminder about fast-forward merges, check out the previous chapter). As a result, <code>main</code> and <code>paul_branch</code> now point to the same commit:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/fast_forward_merge_result.png" alt="The result of a fast-forward merge" width="600" height="400" loading="lazy">
<em>The result of a fast-forward merge</em></p>
<h3 id="heading-advanced-rebasing-in-git">Advanced Rebasing in Git</h3>
<p>Now that you understand the basics of rebase, it is time to consider more advanced cases, where additional switches and arguments to the rebase command will come in handy.</p>
<p>In the previous example, when you only used <code>rebase</code> (without additional switches), Git replayed all the commits from the common ancestor to the tip of the current branch.</p>
<p>But rebase is a super-power. It's an almighty command capable of…well, rewriting history. And it can come in handy if you want to modify history to make it your own.</p>
<p>Undo the last merge by making <code>main</code> point to "Commit 4" again:</p>
<pre><code class="lang-bash">git reset --hard &lt;ORIGINAL_COMMIT 4&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reset_hard_1.png" alt="&quot;Undoing&quot; the last merge operation" width="600" height="400" loading="lazy">
<em>"Undoing" the last merge operation</em></p>
<p>And undo the rebasing by using:</p>
<pre><code class="lang-bash">git checkout paul_branch
git reset --hard &lt;ORIGINAL_COMMIT 9&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reset_hard_2.png" alt="&quot;Undoing&quot; the rebase operation" width="600" height="400" loading="lazy">
<em>"Undoing" the rebase operation</em></p>
<p>Notice that you got to exactly the same history you used to have:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_undoing_rebase.png" alt="Visualizing the history after &quot;undoing&quot; the rebase operation" width="600" height="400" loading="lazy">
<em>Visualizing the history after "undoing" the rebase operation</em></p>
<p>To be clear, "Commit 9" doesn't just disappear when it's not reachable from the current <code>HEAD</code>. Rather, it's still stored in the object database. And as you used <code>git reset</code> now to change <code>HEAD</code> to point to this commit, you were able to retrieve it, and also its parent commits since they are also stored in the database. Pretty cool, huh? 😎 </p>
<p>You will learn more about <code>git reset</code> in the next part, where we discuss undoing changes in Git.</p>
<p>View the changes that Paul introduced:</p>
<pre><code class="lang-bash">git show HEAD
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_show_HEAD_2.png" alt=" shows the patch introduced by &quot;Commit 9&quot;" width="600" height="400" loading="lazy">
<em><code>git show HEAD</code> shows the patch introduced by "Commit 9"</em></p>
<p>Keep going backwards in the commit graph:</p>
<pre><code class="lang-bash">git show HEAD~
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_show_HEAD-.png" alt=" (same as ) shows the patch introduced by &quot;Commit 8&quot;" width="600" height="400" loading="lazy">
<em><code>git show HEAD~</code> (same as <code>git show HEAD~1</code>) shows the patch introduced by "Commit 8"</em></p>
<p>And one commit further:</p>
<pre><code class="lang-bash">git show HEAD~2
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_show_HEAD-2.png" alt=" shows the patch introduced by &quot;Commit 7&quot;" width="600" height="400" loading="lazy">
<em><code>git show HEAD~2</code> shows the patch introduced by "Commit 7"</em></p>
<p>Perhaps Paul doesn't want this kind of history. Rather, he wants it to seem as if he introduced the changes in "Commit 7" and "Commit 8" as a single commit.</p>
<p>For that, you can use an <strong>interactive rebase</strong>. To do that, we add the <code>-i</code> (or <code>--interactive</code>) switch to the rebase command:</p>
<pre><code class="lang-bash">git rebase -i &lt;SHA_OF_COMMIT_4&gt;
</code></pre>
<p>Or, since main is pointing to "Commit 4", we can run:</p>
<pre><code class="lang-bash">git rebase -i main
</code></pre>
<p>By running this command, you tell Git to use a new base, "Commit 4". So you are asking Git to go back to all commits that were introduced after "Commit 4" and that are reachable from the current <code>HEAD</code>, and replay those commits.</p>
<p>For every commit that is replayed, Git asks us what we'd like to do with it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/interactive_rebase_1.png" alt=" prompts you to select what to do with each commit" width="600" height="400" loading="lazy">
<em><code>git rebase -i main</code> prompts you to select what to do with each commit</em></p>
<p>In this context it's useful to think of a commit as a patch. That is, "Commit 7", as in "the patch that "Commit 7" introduced on top of its parent".</p>
<p>One option is to use <code>pick</code>. This is the default behavior, which tells Git to replay the changes introduced in this commit. In this case, if you just leave it as is - and <code>pick</code> all commits - you will get the same history, and Git won't even create new commit objects.</p>
<p>Another option is <code>squash</code>. A <em>squashed</em> commit will have its contents "folded" into the contents of the commit preceding it. So in our case, Paul would like to squash "Commit 8" into "Commit 7":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/interactive_rebase_2.png" alt="Squashing &quot;Commit 8&quot; into &quot;Commit 7&quot;" width="600" height="400" loading="lazy">
<em>Squashing "Commit 8" into "Commit 7"</em></p>
<p>As you can see, <code>git rebase -i</code> provides additional options, but we won't go into all of them in this chapter. If you allow the rebase to run, you will get prompted to select a commit message for the newly created commit (that is, the one that introduced the changes of both "Commit 7" and "Commit 8"):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/interactive_rebase_3.png" alt="Providing the commit message: Commits 7+8" width="600" height="400" loading="lazy">
<em>Providing the commit message: Commits 7+8</em></p>
<p>And look at the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_interactive_rebase.png" alt="The history after the interactive rebase" width="600" height="400" loading="lazy">
<em>The history after the interactive rebase</em></p>
<p>Exactly as we wanted! On <code>paul_branch</code>, we have "Commit 9" (of course, it's a different object than the original "Commit 9"). This object points to "Commits 7+8", which is a single commit introducing the changes of both the original "Commit 7" and the original "Commit 8". This commit's parent is "Commit 4", where <code>main</code> is pointing to.</p>
<p>Oh wow, isn't that cool? 😎</p>
<p><code>git rebase</code> grants you unlimited control over the shape of any branch. You can use it to reorder commits, or to remove incorrect changes, or modify a change in retrospect. Alternatively, you could perhaps move the base of your branch onto another commit, any commit that you wish.</p>
<h3 id="heading-how-to-use-the-onto-switch-of-git-rebase">How to Use the <code>--onto</code> Switch of <code>git rebase</code></h3>
<p>Let's consider one more example. Get to <code>main</code> again:</p>
<pre><code class="lang-bash">git checkout main
</code></pre>
<p>And delete the pointers to paul_branch and john_branch so you don't see them in the commit graph anymore:</p>
<pre><code class="lang-bash">git branch -D paul_branch
git branch -D john_branch
</code></pre>
<p>Next, branch from <code>main</code> to a new branch:</p>
<pre><code class="lang-bash">git checkout -b new_branch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_new_branch.png" alt="Creating  that diverges from " width="600" height="400" loading="lazy">
_Creating <code>new_branch</code> that diverges from <code>main</code>_</p>
<p>This is the clean history you should have:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_new_branch.png" alt="A clean history with  that diverges from " width="600" height="400" loading="lazy">
_A clean history with <code>new_branch</code> that diverges from <code>main</code>_</p>
<p>Now, change the file <code>code.py</code> (for example, add a new function) and commit your changes:</p>
<pre><code class="lang-bash">nano code.py
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_1.png" alt="Adding the function  to " width="600" height="400" loading="lazy">
_Adding the function <code>new_branch</code> to <code>code.py</code>_</p>
<pre><code class="lang-bash">git add code.py
git commit -m <span class="hljs-string">"Commit 10"</span>
</code></pre>
<p>Get back to <code>main</code>:</p>
<pre><code class="lang-bash">git checkout main
</code></pre>
<p>And introduce another change - adding a docstring at the beginning of the file:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_2.png" alt="Added a docstring at the beginning of the file" width="600" height="400" loading="lazy">
<em>Added a docstring at the beginning of the file</em></p>
<p>Time to stage and commit these changes:</p>
<pre><code class="lang-bash">git add code.py
git commit -m <span class="hljs-string">"Commit 11"</span>
</code></pre>
<p>And yet another change, perhaps add <code>@Author</code> to the docstring:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_3.png" alt="Added  to the docstring" width="600" height="400" loading="lazy">
<em>Added <code>@Author</code> to the docstring</em></p>
<p>Commit this change as well:</p>
<pre><code class="lang-bash">git add code.py
git commit -m <span class="hljs-string">"Commit 12"</span>
</code></pre>
<p>Oh wait, now I realize that I wanted you to make the changes introduced in "Commit 11" as a part of the <code>new_branch</code>. Ugh. What can you do?</p>
<p>Consider the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_12-2.png" alt="The history after introducing &quot;Commit 12&quot;" width="600" height="400" loading="lazy">
<em>The history after introducing "Commit 12"</em></p>
<p>Instead of having "Commit 11" reside only on the <code>main</code> branch, I want it to be on <em>both</em> the <code>main</code> branch as well as <code>new_branch</code>. Visually, I would want to <em>move</em> it down the graph here:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/push_commit_10_down.png" alt="Visually, I want you to &quot;push down&quot; &quot;Commit 10&quot;" width="600" height="400" loading="lazy">
<em>Visually, I want you to "push down" "Commit 10"</em></p>
<p>Can you see where I am going? 😇</p>
<p>Well, <code>rebase</code> allows you to basically replay the changes introduced in <code>new_branch</code>, those introduced in "Commit 10", as if they had been originally conducted on "Commit 11", rather than "Commit 4".</p>
<p>To do that, you can use other arguments of <code>git rebase</code>. Specifically, you can use <code>git rebase --onto</code>, which optionally takes three parameters:</p>
<pre><code class="lang-bash">git rebase --onto &lt;new_parent&gt; &lt;old_parent&gt; &lt;until&gt;
</code></pre>
<p>That is, you take all commits between <code>old_parent</code> and <code>until</code>, and you "cut" and "paste" them <em>onto</em> <code>new_parent</code>.</p>
<p>In this case, you'd tell Git that you want to take all the history introduced between the common ancestor of <code>main</code> and <code>new_branch</code>, which is "Commit 4", and have the new base for that history be "Commit 11". To do that, use:</p>
<pre><code class="lang-bash">git rebase --onto &lt;SHA_OF_COMMIT_11&gt; main new_branch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/rebase_onto_1.png" alt="The history before and after the rebase, &quot;Commit 10&quot; has been &quot;pushed&quot;" width="600" height="400" loading="lazy">
<em>The history before and after the rebase, "Commit 10" has been "pushed"</em></p>
<p>And look at our beautiful history! 😍</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/rebase_onto_2.png" alt="The history before and after the rebase, &quot;Commit 10&quot; has been &quot;pushed&quot;" width="600" height="400" loading="lazy">
<em>The history before and after the rebase, "Commit 10" has been "pushed"</em></p>
<p>Let's consider another case.</p>
<p>Say I started working on a new feature, and by mistake I started working from <code>feature_branch_1</code>, rather than from <code>main</code>.</p>
<p>So to emulate this, create <code>feature_branch_1</code>:</p>
<pre><code class="lang-bash">git checkout main
git checkout -b feature_branch_1
</code></pre>
<p>And erase <code>new_branch</code> so you don't see it in the graph anymore:</p>
<pre><code class="lang-bash">git branch -D new_branch
</code></pre>
<p>Create a simple Python file called <code>1.py</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/1_py_1.png" alt="A new file, , with " width="600" height="400" loading="lazy">
<em>A new file, <code>1.py</code>, with <code>print('Hello world!')</code></em></p>
<p>Stage and commit this file:</p>
<pre><code class="lang-bash">git add 1.py
git commit -m  <span class="hljs-string">"Commit 13"</span>
</code></pre>
<p>Now branch out from <code>feature_branch_1</code> (this is the mistake you will later fix):</p>
<pre><code class="lang-bash">git checkout -b feature_branch_2
</code></pre>
<p>And create another file, <code>2.py</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/2_py_1.png" alt="Creating " width="600" height="400" loading="lazy">
<em>Creating <code>2.py</code></em></p>
<p>Stage and commit this file as well:</p>
<pre><code class="lang-bash">git add 2.py
git commit -m  <span class="hljs-string">"Commit 14"</span>
</code></pre>
<p>And introduce some more code to <code>2.py</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/2_py_2.png" alt="Modifying " width="600" height="400" loading="lazy">
<em>Modifying <code>2.py</code></em></p>
<p>Stage and commit these changes too:</p>
<pre><code class="lang-bash">git add 2.py
git commit -m  <span class="hljs-string">"Commit 15"</span>
</code></pre>
<p>So far you should have this history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_15.png" alt="The history after introducing &quot;Commit 15&quot;" width="600" height="400" loading="lazy">
<em>The history after introducing "Commit 15"</em></p>
<p>Get back to <code>feature_branch_1</code> and edit <code>1.py</code>:</p>
<pre><code class="lang-bash">git checkout feature_branch_1
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/1_py_2.png" alt="Modifying " width="600" height="400" loading="lazy">
<em>Modifying <code>1.py</code></em></p>
<p>Now stage and commit:</p>
<pre><code class="lang-bash">git add 1.py
git commit -m  <span class="hljs-string">"Commit 16"</span>
</code></pre>
<p>Your history should look like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_16-1.png" alt="The history after introducing &quot;Commit 16&quot;" width="600" height="400" loading="lazy">
<em>The history after introducing "Commit 16"</em></p>
<p>Say now you realize that you've made a mistake. You actually wanted <code>feature_branch_2</code> to be born from the <code>main</code> branch, rather than from <code>feature_branch_1</code>.</p>
<p>How can you achieve that?</p>
<p>Try to think about it given the history graph and what you've learned about the <code>--onto</code> flag for the <code>rebase</code> command.</p>
<p>Well, you want to "replace" the parent of your first commit on <code>feature_branch_2</code>, which is "Commit 14", so that it's on top of <code>main</code> branch - in this case, "Commit 12" - rather than the beginning of <code>feature_branch_1</code> - in this case, "Commit 13". So again, you will be creating a <em>new base</em>, this time for the first commit on <code>feature_branch_2</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/plan_commit14_15.png" alt="You want to move around &quot;Commit 14&quot; and &quot;Commit 15&quot;" width="600" height="400" loading="lazy">
<em>You want to move around "Commit 14" and "Commit 15"</em></p>
<p>How would you do that?</p>
<p>First, switch to <code>feature_branch_2</code>:</p>
<pre><code class="lang-bash">git checkout feature_branch_2
</code></pre>
<p>And now you can use:</p>
<pre><code class="lang-bash">git rebase --onto main &lt;SHA_OF_COMMIT_13&gt;
</code></pre>
<p>This tells Git to take the history with "Commit 13" as a base, and change that base to be "Commit 12" (pointed to by <code>main</code>) instead.</p>
<p>As a result, you have <code>feature_branch_2</code> based on <code>main</code> rather than <code>feature_branch_1</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/rebase_onto_3.png" alt="The commit history after performing rebase" width="600" height="400" loading="lazy">
<em>The commit history after performing rebase</em></p>
<p>The syntax of the command is:</p>
<pre><code class="lang-bash">git rebase --onto &lt;new_parent&gt; &lt;old_parent&gt;
</code></pre>
<h3 id="heading-how-to-rebase-on-a-single-branch">How to Rebase on a Single Branch</h3>
<p>You can also use <code>git rebase</code> while looking at the history of a single branch.</p>
<p>Let's see if you can help me here.</p>
<p>Say I worked from <code>feature_branch_2</code>, and specifically edited the file <code>code.py</code>. I started by changing all strings to be wrapped by double quotes rather than single quotes:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_4.png" alt="Changing  into  in " width="600" height="400" loading="lazy">
<em>Changing <code>'</code> into <code>"</code> in <code>code.py</code></em></p>
<p>Then, I staged and committed:</p>
<pre><code class="lang-bash">git add code.py
git commit -m <span class="hljs-string">"Commit 17"</span>
</code></pre>
<p>I then decided to add a new function at the beginning of the file:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_5.png" alt="Adding the function " width="600" height="400" loading="lazy">
_Adding the function <code>another_feature</code>_</p>
<p>Again, I staged and committed:</p>
<pre><code class="lang-bash">git add code.py
git commit -m <span class="hljs-string">"Commit 18"</span>
</code></pre>
<p>And now I realized that I actually forgot to change the single quotes to double quotes wrapping <code>__main__</code> (as you might have noticed), so I did that too:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_6.png" alt="Changing  into " width="600" height="400" loading="lazy">
<em>Changing <code>'__main__'</code> into <code>"__main__"</code></em></p>
<p>Of course, I staged and committed this change:</p>
<pre><code class="lang-bash">git add code.py
git commit -m <span class="hljs-string">"Commit 19"</span>
</code></pre>
<p>Now, consider the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_19.png" alt="The commit history after introducing &quot;Commit 19&quot;" width="600" height="400" loading="lazy">
<em>The commit history after introducing "Commit 19"</em></p>
<p>It isn't really nice, is it? I mean, I have two commits that are related to one another, "Commit 17" and "Commit 19" (turning <code>'</code>s into <code>"</code>s), but they are split by the unrelated "Commit 18" (where I added a new function). What can we do? Can you help me?</p>
<p>Intuitively, I want to edit the history here:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/plan_edit_commits_17_18.png" alt="These are the commits I want to edit" width="600" height="400" loading="lazy">
<em>These are the commits I want to edit</em></p>
<p>So, what would you do?</p>
<p>You are right!</p>
<p>I can <code>rebase</code> the history from "Commit 17" to "Commit 19", on top of "Commit 15". To do that:</p>
<pre><code class="lang-bash">git rebase --interactive --onto &lt;SHA_OF_COMMIT_15&gt; &lt;SHA_OF_COMMIT_15&gt;
</code></pre>
<p>Notice I specified "Commit 15" as the beginning of the range of commits, excluding this commit. And I didn't need to explicitly specify <code>HEAD</code> as the last parameter.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/rebase_onto_4.png" alt="Using  on a single branch" width="600" height="400" loading="lazy">
<em>Using <code>rebase --onto</code> on a single branch</em></p>
<p>(Note: If you follow the steps above with my repository and get a merge conflict, you may have a different configuration than on my machine with regards to whitespace characters at line endings. In that case, you can add the <code>--ignore-whitespace</code> switch to the <code>rebase</code> command, resulting in the following command: <code>git rebase --ignore-whitespace --interactive --onto &lt;SHA_OF_COMMIT_15&gt; &lt;SHA_OF_COMMIT_15&gt;</code>. If you are curious to find out more about this issue, search for <code>autocrlf</code>.)</p>
<p>After following your advice and running the <code>rebase</code> command (thanks! 😇) I get the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/interactive_rebase_4.png" alt="Interactive rebase" width="600" height="400" loading="lazy">
<em>Interactive rebase</em></p>
<p>So what would I do? I want to put "Commit 19" before "Commit 18", so it comes right after "Commit 17". I can go further and <code>squash</code> them together, like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/interactive_rebase_5.png" alt="Interactive rebase - changing the order of commit and squashing" width="600" height="400" loading="lazy">
<em>Interactive rebase - changing the order of commit and squashing</em></p>
<p>Now when I get prompted for a commit message, I can provide the message "Commit 17+19":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/interactive_rebase_6.png" alt="Providing a commit message" width="600" height="400" loading="lazy">
<em>Providing a commit message</em></p>
<p>And now, see our beautiful history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/rebase_onto_5.png" alt="The resulting history" width="600" height="400" loading="lazy">
<em>The resulting history</em></p>
<p>Thanks again!</p>
<h3 id="heading-more-rebase-use-cases-more-practice">More Rebase Use Cases + More Practice</h3>
<p>By now I hope you feel comfortable with the syntax of rebase. The best way to actually understand it is to consider various cases and figure out how to solve them yourself.</p>
<p>With the upcoming use cases, I strongly suggest you stop reading after I've introduced each use case, and then try to solve it on your own.</p>
<h4 id="heading-how-to-exclude-commits">How to Exclude Commits</h4>
<p>Say you have this history on another repo:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/another_history_1.png" alt="Another commit history" width="600" height="400" loading="lazy">
<em>Another commit history</em></p>
<p>Before playing around with it, store a tag to "Commit F" so you can get back to it later:</p>
<pre><code class="lang-bash">git tag original_commit_f
</code></pre>
<p>(A tag is a named reference to a commit, just like a branch - but it doesn't change when you add additional commits. It is like a constant named reference.)</p>
<p>Now, you actually don't want the changes in "Commit C" and "Commit D" to be included. You could use an interactive rebase like before and remove their changes. Or, you could use <code>git rebase --onto</code> again. How would you use <code>--onto</code> in order to "remove" these two commits?</p>
<p>You can rebase <code>HEAD</code> on top of "Commit B", where the old parent was actually "Commit D", and now it should be "Commit B". Consider the history again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/another_history_1-1.png" alt="The history again" width="600" height="400" loading="lazy">
<em>The history again</em></p>
<p>Rebasing so that "Commit B" is the base of "Commit E" means "moving" both "Commit E" and "Commit F", and giving them another base - "Commit B". Can you come up with the command yourself?</p>
<pre><code class="lang-bash">git rebase --onto &lt;SHA_OF_COMMIT_B&gt; &lt;SHA_OF_COMMIT_D&gt; HEAD
</code></pre>
<p>Notice that using the syntax above (exactly as provided) would <em>not</em> move <em>main</em> to point to the new commit, so the result is a "detached" <code>HEAD</code>. If you use <code>gg</code> or another tool that displays the history reachable from branches, it might confuse you:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/rebase_onto_6.png" alt="Rebasing with  results in a detached " width="600" height="400" loading="lazy">
<em>Rebasing with <code>--onto</code> results in a detached <code>HEAD</code></em></p>
<p>But if you simply use <code>git log</code> (or my alias <code>git lol</code>), you will see the desired history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_lol.png" alt="The resulting history" width="600" height="400" loading="lazy">
<em>The resulting history</em></p>
<p>I don't know about you, but these kinds of things make me really happy. 😊😇</p>
<p>By the way, you could omit <code>HEAD</code> from the previous command as this is the default value for the third parameter. So just using:</p>
<pre><code class="lang-bash">git rebase --onto &lt;SHA_OF_COMMIT_B&gt; &lt;SHA_OF_COMMIT_D&gt;
</code></pre>
<p>Would have the same effect. The last parameter actually tells Git where the end of the current sequence of commits to rebase is. So the syntax of <code>git rebase --onto</code> with three arguments is:</p>
<pre><code class="lang-bash">git rebase --onto &lt;new_parent&gt; &lt;old_parent&gt; &lt;until&gt;
</code></pre>
<h4 id="heading-how-to-move-commits-across-branches">How to Move Commits Across Branches</h4>
<p>So let's say we get to the same history as before:</p>
<pre><code class="lang-bash">git checkout original_commit_f
</code></pre>
<p>And now I want only "Commit E" to be on a branch based on "Commit B". That is, I want to have a new branch, branching from "Commit B", with only "Commit E".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/another_history_2.png" alt="The current history, considering &quot;Commit E&quot;" width="600" height="400" loading="lazy">
<em>The current history, considering "Commit E"</em></p>
<p>So, what does this mean in terms of <code>rebase</code>? Consider the image above. What commit (or commits) should I rebase, and which commit would be the new base?</p>
<p>I know I can count on you here 😉</p>
<p>What I want is to take "Commit E", and this commit only, and change its base to be "Commit B". In other words, to replay the changes introduced in "Commit E" onto "Commit B".</p>
<p>Can you apply that logic to the syntax of git rebase?</p>
<p>Here it is (this time I'm writing <code>&lt;COMMIT_X&gt;</code> instead of <code>&lt;SHA_OF_COMMIT_X&gt;</code>, for brevity):</p>
<pre><code class="lang-bash">git rebase --onto &lt;COMMIT_B&gt; &lt;COMMIT_D&gt; &lt;COMMIT_E&gt;
</code></pre>
<p>Now the history looks like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_rebase_3.png" alt="The history after rebase" width="600" height="400" loading="lazy">
<em>The history after rebase</em></p>
<p>Notice that <code>rebase</code> moved <code>HEAD</code>, but not any other reference named (such as a branch or a tag). In other words, you are in a detached <code>HEAD</code> state. So here too, using <code>gg</code> or another tool that displays the history reachable from branches and tags might confuse you. You can use <code>git log</code> (or my alias <code>git lol</code>) to display the reachable history from <code>HEAD</code>.</p>
<p>Awesome!</p>
<h3 id="heading-a-note-about-conflicts">A Note About Conflicts</h3>
<p>Note that when performing a rebase, you may run into conflicts just as when merging. You may have conflicts because, when rebasing, you are trying to apply patches on a different base, perhaps where the patches do not apply.</p>
<p>For example, consider the previous repository again, and specifically, consider the change introduced in "Commit 12", pointed to by <code>main</code>:</p>
<pre><code class="lang-bash">git show main
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/patch_commit_12.png" alt="The patch introduced in &quot;Commit 12&quot;" width="600" height="400" loading="lazy">
<em>The patch introduced in "Commit 12"</em></p>
<p>I already covered the format of <code>git diff</code> in detail in <a class="post-section-overview" href="#heading-chapter-6-diffs-and-patches">chapter 6</a>, but as a quick reminder, this commit instructs Git to add a line after the two lines of context:</p>
<pre><code class="lang-patch">
</code></pre>
<p>This is a sample file</p>
<pre><code>
And before these three lines <span class="hljs-keyword">of</span> context:

<span class="hljs-string">``</span><span class="hljs-string">`patch</span>
</code></pre><p>def new_feature():
  print('new feature')</p>
<pre><code>
Say you are trying to rebase <span class="hljs-string">"Commit 12"</span> onto another commit. If, <span class="hljs-keyword">for</span> some reason, these context lines don<span class="hljs-string">'t exist as they do in the patch on the commit you are rebasing onto, then you will have a conflict.

### Zooming Out for the Big Picture

![Comparing rebase and merge](https://www.freecodecamp.org/news/content/images/2023/12/compare_rebase_merge.png)
_Comparing rebase and merge_

In the beginning of this chapter, I started by mentioning the similarity between `git merge` and `git rebase`: both are used to integrate changes introduced in different histories.

But, as you now know, they are very different in how they operate. While merging results in a _diverged_ history, rebasing results in a _linear_ history. Conflicts are possible in both cases. And there is one more column described in the table above that requires some close attention.

Now that you know what "Git rebase" is, and how to use interactive rebase or rebase `--onto`, as I hope you agree, `git rebase` is a super powerful tool. Yet, it has one huge drawback when compared with merging.

**Git rebase changes the history.**

This means that you should **not** rebase commits that exist outside your local copy of the repository, and that other people may have based their commits on.

In other words, if the only commits in question are those you created locally - go ahead, use rebase, go wild.

But if the commits have been pushed, this can lead to a huge problem - as someone else may rely on these commits that you later overwrite, and then you and they will have different versions of the repository.

This is unlike `merge` which, as we have seen, does not modify history.

For example, consider the last case where we rebased and resulted in this history:

![The history after rebase](https://www.freecodecamp.org/news/content/images/2023/12/history_after_rebase_3-1.png)
_The history after rebase_

Now, assume that I have already pushed this branch to the remote. And after I had pushed the branch, another developer pulled it and branched out from "Commit C". The other developer didn'</span>t know that meanwhile, I was locally rebasing my branch, and would later push it again.

This results <span class="hljs-keyword">in</span> an inconsistency: the other developer works <span class="hljs-keyword">from</span> a commit that is no longer available on my copy <span class="hljs-keyword">of</span> the repository.

I will not elaborate on what exactly <span class="hljs-built_in">this</span> causes <span class="hljs-keyword">in</span> <span class="hljs-built_in">this</span> book, <span class="hljs-keyword">as</span> my main message is that you should definitely avoid such cases. If you<span class="hljs-string">'re interested in what would actually happen, I'</span>ll leave a link to a useful resource <span class="hljs-keyword">in</span> the [additional references](#heading-additional-references-by-part). For now, <span class="hljs-keyword">let</span><span class="hljs-string">'s summarize what we have covered.

### Recap - Understanding Git Rebase

In this chapter, you learned about `git rebase`, a super-powerful tool to rewrite history in Git. You considered a few use cases where git rebase can be helpful, and how to use it with one, two, or three parameters, with and without the `--onto` switch.

I hope I was able to convince you that `git rebase` is powerful - but also that it is quite simple once you get the gist. It is a tool you can use to "copy-paste" commits (or, more accurately, patches). And it'</span>s a useful tool to have under your belt. In essence, <span class="hljs-string">`git rebase`</span> takes the patches introduced by commits, and replays them on another commit. As described <span class="hljs-keyword">in</span> <span class="hljs-built_in">this</span> chapter, <span class="hljs-built_in">this</span> is useful <span class="hljs-keyword">in</span> many different scenarios.

## Part <span class="hljs-number">2</span> - Summary

In <span class="hljs-built_in">this</span> part you learned about branching and integrating changes <span class="hljs-keyword">in</span> Git.

You learned what a **diff** is, and the difference between a diff and a **patch**. You also learned how the output <span class="hljs-keyword">of</span> <span class="hljs-string">`git diff`</span> is constructed.

Understanding diffs is a major milestone <span class="hljs-keyword">for</span> understanding many other processes within Git such <span class="hljs-keyword">as</span> merging or rebasing.

Then, you got an extensive overview <span class="hljs-keyword">of</span> merging <span class="hljs-keyword">with</span> Git. You learned that **merging** is the process <span class="hljs-keyword">of</span> **combining the recent changes <span class="hljs-keyword">from</span> several branches into a single <span class="hljs-keyword">new</span> commit**. The <span class="hljs-keyword">new</span> commit has multiple parents - those commits which had been the tips <span class="hljs-keyword">of</span> the branches that were merged. In most cases, merging combines the changes <span class="hljs-keyword">from</span> two branches, and the resulting merge commit then has two parents - one <span class="hljs-keyword">from</span> each branch.

We considered a simple, fast-forward merge, which is possible when one branch diverged <span class="hljs-keyword">from</span> the base branch, and then just added commits on top <span class="hljs-keyword">of</span> the base branch.

We then considered three-way merges, and explained the three-stage process:

* First, Git locates the merge base. As a reminder, <span class="hljs-built_in">this</span> is the first commit that is reachable <span class="hljs-keyword">from</span> both branches.
* Second, Git calculates two diffs - one diff <span class="hljs-keyword">from</span> the merge base to the _first_ branch, and another diff <span class="hljs-keyword">from</span> the merge base to the _second_ branch. Git generates patches based on those diffs.
* Third and last, Git applies both patches to the merge base using a <span class="hljs-number">3</span>-way merge algorithm. The result is the state <span class="hljs-keyword">of</span> the <span class="hljs-keyword">new</span> merge commit.

You saw the output <span class="hljs-keyword">of</span> <span class="hljs-string">`git diff`</span> when we are <span class="hljs-keyword">in</span> a conflicting state, and how to resolve conflicts either manually or <span class="hljs-keyword">with</span> VS Code.

Ultimately, you got to know Git rebase. You saw that <span class="hljs-string">`git rebase`</span> is powerful - but also that it is quite simple once you understand what it does. It is a tool to <span class="hljs-string">"copy-paste"</span> commits (or, more accurately, patches).

![Comparing rebase and merge](https:<span class="hljs-comment">//www.freecodecamp.org/news/content/images/2023/12/compare_rebase_merge-1.png)</span>
_Comparing rebase and merge_

Both <span class="hljs-string">`git merge`</span> and <span class="hljs-string">`git rebase`</span> are used to integrate changes introduced <span class="hljs-keyword">in</span> different histories.

Yet, they differ <span class="hljs-keyword">in</span> how they operate. While merging results <span class="hljs-keyword">in</span> a _diverged_ history, rebasing results <span class="hljs-keyword">in</span> a _linear_ history. <span class="hljs-string">`git rebase`</span> _changes_ the history, whereas <span class="hljs-string">`git merge`</span> adds to the existing history.

With <span class="hljs-built_in">this</span> deep understanding <span class="hljs-keyword">of</span> diffs, patches, merge and rebase, you should feel confident introducing changes to a git repository.

The next part will focus on what happens when things go wrong - how you can change history (<span class="hljs-keyword">with</span> or without <span class="hljs-string">`git rebase`</span>), or find <span class="hljs-string">"lost"</span> commits.

# Part <span class="hljs-number">3</span> - Undoing Changes

Did you ever get to a point where you said: <span class="hljs-string">"Uh-oh, what did I just do?"</span> I guess you have, just like about anyone who uses Git.

Perhaps you committed to the wrong branch. Perhaps you lost some code that you had written. Perhaps you committed something that you didn<span class="hljs-string">'t mean to.

This part will give you the tools to rewrite history with confidence, thereby "undoing" all kinds of changes in Git. 

Just like the other parts of the book, this part will be practical yet in-depth - so instead of providing you with a list of things to do when things go wrong, we will understand the underlying mechanisms, so that you will feel confident whenever you get to the "uh-oh" moment. Actually, you will find these moments as opportunities for an interesting challenge, rather than a dreadful scenario.

## Chapter 9 - Git Reset

Our journey starts with a powerful command that can be used to undo many different actions with Git - `git reset`.

### A Short Reminder - Recording Changes

In [chapter 3](#heading-chapter-3-how-to-record-changes-in-git), you learned how to record changes in Git. If you remember everything from this part, feel free to jump to the next section.

It is very useful to think about Git as a system for recording snapshots of a filesystem in time. Considering a Git repository, it has three "states" or "trees":

1. The **working directory**, a directory that has a repository associated with it.
2. The **staging area (index)** which holds the tree for the next commit.
3. The **repository**, which is a collection of commits and references.

![The three "trees" of a Git repo](https://www.freecodecamp.org/news/content/images/2023/12/3_trees.png)
_The three "trees" of a Git repo_

Note regarding the drawing conventions I use: I include `.git` within the working directory, to remind you that it is a folder within the project'</span>s folder on the filesystem. The <span class="hljs-string">`.git`</span> folder actually contains the objects and references <span class="hljs-keyword">of</span> the repository, <span class="hljs-keyword">as</span> explained <span class="hljs-keyword">in</span> [chapter <span class="hljs-number">4</span>](#heading-chapter<span class="hljs-number">-4</span>-how-to-create-a-repo-<span class="hljs-keyword">from</span>-scratch).

#### Hands-on Demonstration

Use <span class="hljs-string">`git init`</span> to initialize a <span class="hljs-keyword">new</span> repository. Write some text into a file called <span class="hljs-string">`1.txt`</span>:

<span class="hljs-string">``</span><span class="hljs-string">`bash
mkdir my_repo
cd my_repo
git init
echo Hello world &gt; 1.txt</span>
</code></pre><p>Out of the three tree states described above, where is <code>1.txt</code> now?</p>
<p>In the working tree, as it hasn't yet been introduced to the index.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/1_txt_working_dir.png" alt="The file  is now a part of the working dir only" width="600" height="400" loading="lazy">
<em>The file <code>1.txt</code> is now a part of the working dir only</em></p>
<p>In order to <em>stage</em> it, to <em>add</em> it to the index, use:</p>
<pre><code class="lang-bash">git add 1.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/1_txt_index.png" alt="Using  stages the file so it is now in the index as well" width="600" height="400" loading="lazy">
<em>Using <code>git add</code> stages the file so it is now in the index as well</em></p>
<p>Notice that once you stage <code>1.txt</code>, Git creates a blob object with the content of this file, and adds it to the internal object database (within <code>.git</code> folder), as covered in <a class="post-section-overview" href="#heading-chapter-3-how-to-record-changes-in-git">chapter 3</a> and <a class="post-section-overview" href="#heading-chapter-4-how-to-create-a-repo-from-scratch">chapter 4</a>. I do not draw it as part of the "repository" as in this representation, the "repository" refers to a tree of commits and their references, and this blob has not been a part of any commit.</p>
<p>Now, use <code>git commit</code> to commit your changes to the repository:</p>
<pre><code class="lang-bash">git commit -m <span class="hljs-string">"Commit 1"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_1.png" alt="Using  creates a commit object in the repository" width="600" height="400" loading="lazy">
<em>Using <code>git commit</code> creates a commit object in the repository</em></p>
<p>You created a new <strong>commit</strong> object, which includes a pointer to a <strong>tree</strong> describing the entire <strong>working tree</strong>. In this case, this tree consists only of <code>1.txt</code> within the root folder. In addition to a pointer to the tree, the commit object includes metadata, such as timestamps and author information.</p>
<p>When considering the diagrams, notice that we only have a single copy of the file <code>1.txt</code> on disk, and a corresponding blob object in Git's object database. The "repository" tree now shows this file as it is part of the active commit - that is, the commit object "Commit 1" points to a tree that points to the blob with the contents of <code>1.txt</code>, the same blob that the index is pointing to.</p>
<p>For more information about the objects in Git (such as commits and trees), refer to <a class="post-section-overview" href="#heading-chapter-1-git-objects">chapter 1</a>.</p>
<p>Next, create a new file, and add it to the index, as before:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> second file &gt; 2.txt
git add 2.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/2_txt_index.png" alt="The file  is in the working dir and the index after staging it with " width="600" height="400" loading="lazy">
<em>The file <code>2.txt</code> is in the working dir and the index after staging it with <code>git add</code></em></p>
<p>Next, commit:</p>
<pre><code class="lang-bash">git commit -m <span class="hljs-string">"Commit 2"</span>
</code></pre>
<p>Importantly, <code>git commit</code> does two things:</p>
<p>First, it creates a <strong>commit object</strong>, so there is an object within Git's internal object database with a corresponding SHA-1 value. This new commit object also points to the parent commit. That is the commit that <code>HEAD</code> was pointing to when you wrote the <code>git commit</code> command.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/new_commit_object.png" alt="A new commit object has been created, at first —  still points to the previous commit" width="600" height="400" loading="lazy">
<em>A new commit object has been created, at first - <code>main</code> still points to the previous commit</em></p>
<p>Second, <code>git commit</code> <strong>moves the pointer of the active branch</strong> — in our case, that would be <code>main</code>, to point to the newly created commit object.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_updates_active_branch.png" alt=" also updates the active branch to point to the newly created commit object" width="600" height="400" loading="lazy">
<em><code>git commit</code> also updates the active branch to point to the newly created commit object</em></p>
<h3 id="heading-introducing-git-reset">Introducing <code>git reset</code></h3>
<p>You will now learn how to reverse the process of introducing a commit. For that, you will get to know the command <code>git reset</code>.</p>
<h4 id="heading-git-reset-soft"><code>git reset --soft</code></h4>
<p>The very last step you did before was to <code>git commit</code>, which actually means two things — Git created a commit object and moved <code>main</code>, the active branch. To undo this step, use the following command:</p>
<pre><code class="lang-bash">git reset --soft HEAD~1
</code></pre>
<p>The syntax <code>HEAD~1</code> refers to the first parent of <code>HEAD</code>. Consider a case where I had more than one commit in the commit-graph, say "Commit 3" pointing to "Commit 2", which is, in turn, pointing to "Commit 1. And consider <code>HEAD</code> was pointing to "Commit 3". You could use <code>HEAD~1</code> to refer to "Commit 2", and <code>HEAD~2</code> would refer to "Commit 1".</p>
<p>So, back to the command: <code>git reset --soft HEAD~1</code></p>
<p>This command asks Git to change whatever <code>HEAD</code> is pointing to. (Note: In the diagrams below, I use <code>*HEAD</code> for "whatever <code>HEAD</code> is pointing to".) In our example, <code>HEAD</code> is pointing to <code>main</code>. So Git will only change the pointer of <code>main</code> to point to <code>HEAD~1</code>. That is, <code>main</code> will point to "Commit 1".</p>
<p>However, this command did <strong>not</strong> affect the state of the index or the working tree. So if you use <code>git status</code> you will see that <code>2.txt</code> is staged, just like before you ran <code>git commit</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_status_after_reset_soft.png" alt=" shows that  is in the index, but not in the active commit" width="600" height="400" loading="lazy">
<em><code>git status</code> shows that <code>2.txt</code> is in the index, but not in the active commit</em></p>
<p>The state is now:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/reset_soft_1.png" alt="Resetting  to &quot;Commit 1&quot;" width="600" height="400" loading="lazy">
<em>Resetting <code>main</code> to "Commit 1"</em></p>
<p>(Note: I removed <code>2.txt</code> from the "repository" in the diagram as it is not part of the active commit - that is, the tree pointed to by "Commit 1" does not reference this file. However, it has not been removed from the file system - as it still exists in the working tree and the index.)</p>
<p>What about <code>git log</code>? It will start from <code>HEAD</code> , go to <code>main</code>, and then to "Commit 1":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_after_reset_soft.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git log</code></em></p>
<p>Notice that this means that "Commit 2" is no longer reachable from our history.</p>
<p>Does that mean the commit object of "Commit 2" is deleted?</p>
<p>No, it's not deleted. It still resides within Git's internal object database of objects.</p>
<p>If you push the current history now, by using <code>git push</code>, Git will not push "Commit 2" to the remote server (as it is not reachable from the current <code>HEAD</code>), but the commit object <em>still exists</em> on your local copy of the repository.</p>
<p>Now, commit again - and use the commit message of "Commit 2.1" to differentiate this new object from the original "Commit 2":</p>
<pre><code class="lang-bash">git commit -m <span class="hljs-string">"Commit 2.1"</span>
</code></pre>
<p>This is the resulting state:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_2_1.png" alt="Creating a new commit" width="600" height="400" loading="lazy">
<em>Creating a new commit</em></p>
<p>I omitted "Commit 2" as it is not reachable from <code>HEAD</code>, even though its object exists in Git's internal object database.</p>
<p>Why are "Commit 2" and "Commit 2.1" different? Even if we used the same commit message, and even though they point to the same tree object (of the root folder consisting of <code>1.txt</code> and <code>2.txt</code>), they still have different timestamps, as they were created at different times. Both "Commit 2" and "Commit 2.1" now point to "Commit 1", but only "Commit 2.1" is reachable from <code>HEAD</code>.</p>
<h4 id="heading-git-reset-mixed"><code>git reset --mixed</code></h4>
<p>It's time to undo even further. This time, use:</p>
<pre><code class="lang-bash">git reset --mixed HEAD~1
</code></pre>
<p>(Note: <code>--mixed</code> is the default switch for <code>git reset</code>.)</p>
<p>This command starts the same as <code>git reset --soft HEAD~1</code>. That is, the command takes the pointer of whatever <code>HEAD</code> is pointing to now, which is the <code>main</code> branch, and sets it to <code>HEAD~1</code>, in our example - "Commit 1".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reset_mixed_1.png" alt="The first step of  is the same as " width="600" height="400" loading="lazy">
<em>The first step of <code>git reset --mixed</code> is the same as <code>git reset --soft</code></em></p>
<p>Next, Git goes further, effectively undoing the changes we made to the index. That is, changing the index so that it matches with the current <code>HEAD</code>, the new <code>HEAD</code> after setting it in the first step.</p>
<p>If we ran <code>git reset --mixed HEAD~1</code>, then <code>HEAD</code> (<code>main</code>) would be set to <code>HEAD~1</code> ("Commit 1"), and then Git would match the index to the state of "Commit 1" - in this case, it means that <code>2.txt</code> would no longer be part of the index.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reset_mixed_2.png" alt="The second step of  is to match the index with the new " width="600" height="400" loading="lazy">
<em>The second step of <code>git reset --mixed</code> is to match the index with the new <code>HEAD</code></em></p>
<p>It's time to create a new commit with the state of the original "Commit 2". This time you need to stage <code>2.txt</code> again before creating it:</p>
<pre><code class="lang-bash">git add 2.txt
git commit -m <span class="hljs-string">"Commit 2.2"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_2_2.png" alt="Creating &quot;Commit 2.2&quot;" width="600" height="400" loading="lazy">
<em>Creating "Commit 2.2"</em></p>
<p>Similarly to "Commit 2.1", I "name" this commit "Commit 2.2" to differentiate it from the original "Commit 2" or "Commit 2.1" - these commits result in the same state as the original "Commit 2", but they are different commit objects.</p>
<h4 id="heading-git-reset-hard"><code>git reset --hard</code></h4>
<p>Go on, undo even more!</p>
<p>This time, use the <code>--hard</code> switch, and run:</p>
<pre><code class="lang-bash">git reset --hard HEAD~1
</code></pre>
<p>Again, Git starts with the <code>--soft</code> stage, setting whatever <code>HEAD</code> is pointing to (<code>main</code>), to <code>HEAD~1</code> ("Commit 1").</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reset_hard_1-1.png" alt="The first step of  is the same as " width="600" height="400" loading="lazy">
<em>The first step of <code>git reset --hard</code> is the same as <code>git reset --soft</code></em></p>
<p>Next, moving on to the <code>--mixed</code> stage, matching the index with <code>HEAD</code>. That is, Git undoes the staging of <code>2.txt</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reset_hard_2-1.png" alt="The second step of  is the same as " width="600" height="400" loading="lazy">
<em>The second step of <code>git reset --hard</code> is the same as <code>git reset --mixed</code></em></p>
<p>Next comes the <code>--hard</code> step, where Git goes even further and matches the working dir with the stage of the index. In this case, it means removing <code>2.txt</code> also from the working dir.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reset_hard_3.png" alt="The third step of  matches the state of the working dir with that of the index" width="600" height="400" loading="lazy">
<em>The third step of <code>git reset --hard</code> matches the state of the working dir with that of the index</em></p>
<p>So to introduce a change to Git, you have three steps: you change the working dir, the index, or the staging area, and then you commit a new snapshot with those changes. To undo these changes:</p>
<ul>
<li>If we use <code>git reset --soft</code>, we undo the commit step.</li>
<li>If we use <code>git reset --mixed</code>, we also undo the staging step.</li>
<li>If we use <code>git reset --hard</code>, we undo the changes to the working dir.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reset_switches.png" alt="The three main switches of " width="600" height="400" loading="lazy">
<em>The three main switches of <code>git reset</code></em></p>
<h3 id="heading-real-life-scenarios">Real-Life Scenarios</h3>
<h4 id="heading-scenario-1">Scenario #1</h4>
<p>So in a real-life scenario, write "I love Git" into a file (<code>love.txt</code>), as we all love Git 😍. Go ahead, stage and commit this as well:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> I love Git &gt; love.txt
git add love.txt
git commit -m <span class="hljs-string">"Commit 2.3"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_2_3.png" alt="Creating &quot;Commit 2.3&quot;" width="600" height="400" loading="lazy">
<em>Creating "Commit 2.3"</em></p>
<p>Also, save a tag so that you can get back to this commit later if needed:</p>
<pre><code class="lang-bash">git tag scenario-1
</code></pre>
<p>Oh, oops!</p>
<p>Actually, I didn't want you to commit it.</p>
<p>What I actually wanted you to do is write some more love words in this file before committing it.</p>
<p>What can you do?</p>
<p>Well, one way to overcome this would be to use <code>git reset --mixed HEAD~1</code>, effectively undoing both the committing and the staging actions you took:</p>
<pre><code class="lang-bash">git reset --mixed HEAD~1
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/reset_commit_2_3.png" alt="Undoing the staging and committing steps" width="600" height="400" loading="lazy">
<em>Undoing the staging and committing steps</em></p>
<p>So <code>main</code> points to "Commit 1" again, and <code>love.txt</code> is no longer a part of the index. However, the file remains in the working dir. You can now add more content to it:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> and Gitting Things Done &gt;&gt; love.txt
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/adding_love_lyrics.png" alt="Adding more love lyrics" width="600" height="400" loading="lazy">
<em>Adding more love lyrics</em></p>
<p>Stage and commit your file:</p>
<pre><code class="lang-bash">git add love.txt
git commit -m <span class="hljs-string">"Commit 2.4"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_2_4.png" alt="Introducing &quot;Commit 2.4&quot;" width="600" height="400" loading="lazy">
<em>Introducing "Commit 2.4"</em></p>
<p>Well done!</p>
<p>You got this clear, nice history of "Commit 2.4" pointing to "Commit 1".</p>
<p>You now have a new tool in your toolbox, <code>git reset</code>.</p>
<p>This tool is super, super useful, and you can accomplish almost anything with it. It's not always the most convenient tool to use, but it's capable of solving almost any rewriting-history scenario if you use it carefully.</p>
<p>For beginners, I recommend using only <code>git reset</code> for almost any time you want to undo in Git. Once you feel comfortable with it, move on to other tools.</p>
<h4 id="heading-scenario-2">Scenario #2</h4>
<p>Let us consider another case.</p>
<p>Create a new file called <code>new.txt</code>; stage and commit:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> this is a new file &gt; new.txt
git add new.txt
git commit -m <span class="hljs-string">"Commit 3"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_3.png" alt="Creating  and &quot;Commit 3&quot;" width="600" height="400" loading="lazy">
<em>Creating <code>new.txt</code> and "Commit 3"</em></p>
<p>(Note: In the drawing I omitted the files from the repository to avoid clutter. Commit 3 includes <code>1.txt</code>, <code>love.txt</code> and <code>new.txt</code> at this stage).</p>
<p>Oops. Actually, that's a mistake. You were on <code>main</code>, and I wanted you to create this commit on a feature branch. My bad 😇</p>
<p>There are two most important tools I want you to take from this chapter. The <em>second</em> is <code>git reset</code>. The first and by far more important one is to whiteboard the current state versus the state you want to be in.</p>
<p>For this scenario, the current state and the desired state look like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/scenario_2.png" alt="Scenario #2: current-vs-desired states" width="600" height="400" loading="lazy">
<em>Scenario #2: current-vs-desired states</em></p>
<p>(Note: In following diagrams, I will refer to the current state as the "original" state - before starting the process of rewriting history.)</p>
<p>You will notice three changes:</p>
<ol>
<li><code>main</code> points to "Commit 3" (the blue one) in the current state, but to "Commit 2.4" in the desired state.</li>
<li><code>feature_branch</code> doesn't exist in the current state, yet it exists and points to "Commit 3" in the desired state.</li>
<li><code>HEAD</code> points to <code>main</code> in the current state, and to <code>feature_branch</code> in the desired state.</li>
</ol>
<p>If you can draw this and you know how to use <code>git reset</code>, you can definitely get yourself out of this situation.</p>
<p>So again, the most important thing is to take a breath and draw this out.</p>
<p>Observing the drawing above, how do you get from the current state to the desired one?</p>
<p>There are a few different ways of course, but I will present one option only for each scenario. Feel free to play around with other options as well.</p>
<p>You can start by using <code>git reset --soft HEAD~1</code>. This would set <code>main</code> to point to the previous commit, "Commit 2.4":</p>
<pre><code class="lang-bash">git reset --soft HEAD~1
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/scenario_2_1.png" alt="Changing ; &quot;Commit 3 is still there, just not reachable from " width="600" height="400" loading="lazy">
<em>Changing <code>main</code>: "Commit 3" is still there, just not reachable from <code>HEAD</code></em></p>
<p>Peeking at the current-vs-desired diagram again, you can see that you need a new branch, right? You can use <code>git switch -c feature_branch</code> for it, or <code>git checkout -b feature_branch</code> (which does the same thing):</p>
<pre><code class="lang-bash">git switch -c feature_branch
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/scenario_2_2.png" alt="Creating  branch" width="600" height="400" loading="lazy">
_Creating <code>feature_branch</code> branch_</p>
<p>This command also updates <code>HEAD</code> to point to the new branch.</p>
<p>Since you used <code>git reset --soft</code>, you didn't change the index, so it currently has exactly the state you want to commit - how convenient! You can simply commit to <code>feature_branch</code>:</p>
<pre><code class="lang-bash">git commit -m <span class="hljs-string">"Commit 3.1"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_3_1.png" alt="Committing to  branch" width="600" height="400" loading="lazy">
_Committing to <code>feature_branch</code> branch_</p>
<p>And you got to the desired state.</p>
<h4 id="heading-scenario-3">Scenario #3</h4>
<p>Ready to apply your knowledge to additional cases?</p>
<p>Still on <code>feature_branch</code>, add some changes to <code>love.txt</code>, and create a new file called <code>cool.txt</code>. Stage them and commit:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> Some changes &gt;&gt; love.txt
<span class="hljs-built_in">echo</span> Git is cool &gt; cool.txt
git add love.txt
git add cool.txt
git commit -m <span class="hljs-string">"Commit 4"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_4.png" alt="The history, as well as the state of the index and the working dir after creating &quot;Commit 4&quot;" width="600" height="400" loading="lazy">
<em>The history, as well as the state of the index and the working dir after creating "Commit 4"</em></p>
<p>Oh, oops, actually I wanted you to create two <em>separate</em> commits, one with each change...</p>
<p>Want to try this one yourself (before reading on)?</p>
<p>You can undo the committing and staging steps:</p>
<pre><code class="lang-bash">git reset --mixed HEAD~1
</code></pre>
<p>Following this command, the index no longer includes those two changes, but they're both still in your file system:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/reset_commit_4.png" alt="Resulting state after using " width="600" height="400" loading="lazy">
<em>Resulting state after using <code>git reset --mixed HEAD~1</code></em></p>
<p>So now, if you only stage <code>love.txt</code>, you can commit it separately:</p>
<pre><code class="lang-bash">git add love.txt
git commit -m <span class="hljs-string">"Love"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_love.png" alt="Resulting state after committing the changes to " width="600" height="400" loading="lazy">
<em>Resulting state after committing the changes to <code>love.txt</code></em></p>
<p>Then, do the same for <code>cool.txt</code>:</p>
<pre><code class="lang-bash">git add cool.txt
git commit -m <span class="hljs-string">"Cool"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_separately.png" alt="Committing separately" width="600" height="400" loading="lazy">
<em>Committing separately</em></p>
<p>Nice!</p>
<h4 id="heading-scenario-4">Scenario #4</h4>
<p>To clear up the state, switch to <code>main</code> and use <code>reset --hard</code> to make it point to "Commit 3.1", while setting the index and the working dir to the state of "Commit 3.1":</p>
<pre><code class="lang-bash">git checkout main
git reset --hard &lt;SHA_OF_COMMIT_3_1&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/reset_main_commit_3_1.png" alt="Resetting  to &quot;Commit 3.1&quot;" width="600" height="400" loading="lazy">
<em>Resetting <code>main</code> to "Commit 3.1"</em></p>
<p>Create another file (<code>another.txt</code>) with some text, and add some text to <code>love.txt</code>. Stage both changes, and commit them:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> Another file &gt; another.txt
<span class="hljs-built_in">echo</span> More love &gt;&gt; love.txt
git add another.txt
git add love.txt
git commit -m <span class="hljs-string">"Commit 4.1"</span>
</code></pre>
<p>This should be the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_more_changes.png" alt="A new commit" width="600" height="400" loading="lazy">
<em>A new commit</em></p>
<p>Oops...</p>
<p>So this time, I wanted it to be on another branch, but not a new branch, rather - an already-existing branch.</p>
<p>So what can you do?</p>
<p>I'll give you a hint. The answer is really short and really easy. What do we do first?</p>
<p>No, not <code>reset</code>. We <em>draw</em>. That's the first thing to do, as it would make everything else so much easier. So this is the current state:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/scenario_4.png" alt="The new commit on  appears blue" width="600" height="400" loading="lazy">
<em>The new commit on <code>main</code> appears blue</em></p>
<p>And the desired state?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/scenario_4_1-1.png" alt="We want the &quot;blue&quot; commit to be on another, , branch\label{fig-scenario-4-1}" width="600" height="400" loading="lazy">
<em>We want the "blue" commit to be on another, <code>existing</code>, branch</em></p>
<p>How do you get from the current state to the desired state, what would be easiest?</p>
<p>One way would be to use <code>git reset</code> as you did before, but there is another way that I would like you to try.</p>
<p>Note that the following commands indeed assume the branch <code>existing</code> exists on your repository, yet you haven't created it earlier. To match a state where this branch actually exists, you can use the following commands:</p>
<pre><code class="lang-bash">git checkout &lt;SHA_OF_COMMIT_1&gt;
git checkout -b existing
<span class="hljs-built_in">echo</span> <span class="hljs-string">"Hello"</span> &gt; x.txt
git add x.txt
git commit -m <span class="hljs-string">"Commit X"</span>
git checkout &lt;SHA_OF_COMMIT_3_1&gt; -- love.txt
git commit -m <span class="hljs-string">"Commit Y"</span>
git checkout main
</code></pre>
<p>(The command <code>git checkout &lt;SHA_OF_COMMIT_3_1&gt; -- love.txt</code> copies the contents of <code>love.txt</code> from "Commit 3.1" to the index and the working dir, so that you can commit it on the <code>existing</code> branch. We need the state of <code>love.txt</code> on "Commit Y" to be the same as of "Commit 3.1" to avoid conflicts.)</p>
<p>Now your history should match the one shown in the picture with the caption "We want the "blue" commit to be on another, <code>existing</code>, branch".</p>
<p>First, move <code>HEAD</code> to point to existing branch:</p>
<pre><code class="lang-bash">git switch existing
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/switch_existing.png" alt="Switch to the  branch" width="600" height="400" loading="lazy">
<em>Switch to the <code>existing</code> branch</em></p>
<p>Intuitively, what you want to do is take the changes introduced in "Commit 4.1", and apply these changes ("copy-paste") on top of <code>existing</code> branch. And Git has a tool just for that.</p>
<p>To ask Git to take the changes introduced between a commit and its parent commit and just apply these changes on the active branch, you can use <code>git cherry-pick</code>, a command we introduced in <a class="post-section-overview" href="#heading-chapter-8-understanding-git-rebase">chapter 8</a>. This command takes the changes introduced in the specified revision and applies them to the state of the active commit. Run:</p>
<pre><code class="lang-bash">git cherry-pick &lt;SHA_OF_COMMIT_4_1&gt;
</code></pre>
<p>You can specify the SHA-1 identifier of the desired commit, but you can also use <code>git cherry-pick main</code>, as the commit whose changes you are applying is the one <code>main</code> is pointing to.</p>
<p><code>git cherry-pick</code> also creates a new commit object, and updates the active branch to point to this new object, so the resulting state would be:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cherry_pick.png" alt="The result after using " width="600" height="400" loading="lazy">
<em>The result after using <code>git cherry-pick</code></em></p>
<p>I mark the commit as "Commit 4.2" since it has a different timestamp, parent and SHA-1 value than "Commit 4.1", though the changes it introduces are the same.</p>
<p>You made good progress - the desired commit is now on the <code>existing</code> branch! But we don't want these changes to exist on <code>main</code> branch. <code>git cherry-pick</code> only applied the changes to the existing branch. How can you remove them from <code>main</code>?</p>
<p>One way would be to switch back to <code>main</code>, and then <code>reset</code> it:</p>
<pre><code class="lang-bash">git switch main
git reset --hard HEAD~1
</code></pre>
<p>And the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/reset_cherry_pick.png" alt="The resulting state after resetting " width="600" height="400" loading="lazy">
<em>The resulting state after resetting <code>main</code></em></p>
<p>You did it!</p>
<p>Note that <code>git cherry-pick</code> actually computes the difference between the specified commit and its parent, and then applies the difference to the active commit. This means that sometimes, Git won't be able to apply those changes due to a conflict.</p>
<p>Also, note that you can ask Git to <code>cherry-pick</code> the changes introduced in any commit, not only commits referenced by a branch.</p>
<h3 id="heading-recap-git-reset">Recap - Git Reset</h3>
<p>In this chapter, we learned how <code>git reset</code> operates, and clarified its three main modes of operation:</p>
<ul>
<li><code>git reset --soft &lt;commit&gt;</code>, which changes whatever <code>HEAD</code> is pointing to - to <code>&lt;commit&gt;</code>.</li>
<li><code>git reset --mixed &lt;commit&gt;</code>, which goes through the <code>--soft</code> stage, and also sets the state of the index to match that of <code>HEAD</code>.</li>
<li><code>git reset --hard &lt;commit&gt;</code>, which goes through the <code>--soft</code> and <code>--mixed</code> stages, and then sets the state of the working dir to match that of the index.</li>
</ul>
<p>You then applied your knowledge about <code>git reset</code> to solve some real-life issues that arise when using Git.</p>
<p>By understanding the way Git operates, and by whiteboarding the current state versus the desired state, you can confidently tackle all kinds of scenarios.</p>
<p>In the future chapters, we will cover additional Git commands and how they can help us solve all kinds of undesired situations.</p>
<h2 id="heading-chapter-10-additional-tools-for-undoing-changes">Chapter 10 - Additional Tools for Undoing Changes</h2>
<p>In the previous chapter, you met <code>git reset</code>. Indeed, <code>git reset</code> is a super powerful tool, and I highly recommend to use it until you feel completely comfortable with it.</p>
<p>Yet, <code>git reset</code> is not the only tool at our disposal. Some of the times, it is not the most convenient tool to use. In others, it's just not enough. This short chapter touches a few tools that are helpful for undoing changes in Git.</p>
<h3 id="heading-git-commit-amend"><code>git commit --amend</code></h3>
<p>Consider <a target="_blank" href="https://www.freecodecamp.org/news/p/f7b355ea-3f22-4613-8218-e95c67779d9f/scenario-1">Scenario #1</a> from the previous chapter again. As a reminder, you wrote "I love Git" into a file (<code>love.txt</code>), staged and committed this file:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/image-52.png" alt="Image" width="600" height="400" loading="lazy">
<em>The state after creating "Commit 2.3"</em></p>
<p>And then I realized I didn't want you to commit it at that state, but rather - write some more love words in this file before committing it.</p>
<p>To match this state, simply checkout the tag you created, which points to "Commit 2.3":</p>
<pre><code class="lang-bash">git checkout scenario-1
</code></pre>
<p>In the previous chapter, when we introduced <code>git reset</code>, you solved this issue by using <code>git reset --mixed HEAD~1</code>, effectively undoing both the committing and the staging actions you took.</p>
<p>Now I would like you to consider another approach. Keep working at the state of the last introduced commit ("Commit 2.3", referenced by the tag "scenario-1"), and make the changes you want:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> And I love this book &gt;&gt; love.txt
</code></pre>
<p>Add this change to the index:</p>
<pre><code class="lang-bash">git add love.txt
</code></pre>
<p>Now, you can use <code>git commit</code> with the <code>--amend</code> switch, which tells it to override the commit <code>HEAD</code> is pointing to. Actually, it will create another, new commit, pointing to <code>HEAD~1</code> ("Commit 1" in our example), and make <code>HEAD</code> point to this newly created commit. By providing the <code>-m</code> argument you can specify a new commit message as well:</p>
<pre><code class="lang-bash">git commit --amend -m <span class="hljs-string">"Commit 2.4"</span>
</code></pre>
<p>After running this command, <code>HEAD</code> points to <code>main</code>, which points to "Commit 2.4", which in turn points to "Commit 1". The previous "Commit 2.3" is no longer reachable from the history.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_amend-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The state after using <code>git commit --amend</code> (Commit "2.3" is unreachable and thus not included in the drawing)</em></p>
<p>This tool is useful when you want to quickly override the last commit you created. Indeed, you could use <code>git reset</code> to accomplish the same thing, but you can view <code>git commit --amend</code> as a more convenient shortcut.</p>
<h3 id="heading-git-revert"><code>git revert</code></h3>
<p>Okay, so another day, another problem.</p>
<p>Add the following text to <code>love.txt</code>, stage and commit as follows:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> This is more tezt &gt;&gt; love.txt
git add love.txt
git commit -m <span class="hljs-string">"Commit 3"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_revert_1-1.png" alt="Committing &quot;More changes&quot;" width="600" height="400" loading="lazy">
<em>The state after committing "Commit 3"</em></p>
<p>And push it to the remote server:</p>
<pre><code class="lang-bash">git push origin HEAD
</code></pre>
<p>Um, oops 😓…</p>
<p>I just noticed something. I had a typo there. I wrote "This is more tezt" instead of "This is more text". Whoops. So what's the big problem now? I <code>push</code>ed, which means that someone else might have already <code>pull</code>ed those changes.</p>
<p>If I override those changes by using <code>git reset</code>, we will have different histories, and all hell might break loose. You can rewrite your own copy of the repo as much as you like until you <code>push</code> it.</p>
<p>Once you <code>push</code> the change, you need to be certain no one else has fetched those changes if you are going to rewrite history.</p>
<p>Alternatively, you can use another tool called <code>git revert</code>. This command takes the commit you're providing it with and computes the diff from its parent commit, just like <code>git cherry-pick</code>, but this time, it computes the <em>reverse</em> changes. That is, if in the specified commit you added a line, the reverse would delete the line, and vice versa. </p>
<p>In our case we are reverting "Commit 3", so the reverse would be to delete the line "This is more tezt" from <code>love.txt</code>. Since "Commit 3" is referenced by <code>main</code> and <code>HEAD</code>, we can use any of these named references in this command:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_revert_2.png" alt="Using  to undo the changes" width="600" height="400" loading="lazy">
<em>Using <code>git revert</code> to undo the changes</em></p>
<p><code>git revert</code> created a new commit object, which means it's an addition to the history. By using <code>git revert</code>, you didn't rewrite history. You admitted your past mistake, and this commit is an acknowledgment that you made a mistake and now you fixed it.</p>
<p>Some would say it's the more mature way. Some would say it's not as clean a history as you would get if you used <code>git reset</code> to rewrite the previous commit. But this is a way to avoid rewriting history.</p>
<p>You can now fix the typo and commit again:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> This is more text &gt;&gt; love.txt
git add love.txt
git commit -m <span class="hljs-string">"Commit 3.1"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_revert_3.png" alt="Redoing the changes" width="600" height="400" loading="lazy">
<em>The resulting state after redoing the changes</em></p>
<p>You can use <code>git revert</code> to revert a commit other than <code>HEAD</code>. Say that you want to reverse the parent of <code>HEAD</code>, you can use:</p>
<pre><code class="lang-bash">git revert HEAD~1
</code></pre>
<p>Or you could provide the SHA-1 of the commit to revert.</p>
<p>Notice that since Git will apply the reverse patch of the previous patch - this operation might fail, as the patch may no longer apply and you might get a conflict.</p>
<h3 id="heading-git-rebase-as-a-tool-for-undoing-things">Git Rebase as a Tool for Undoing Things</h3>
<p>In <a class="post-section-overview" href="#heading-chapter-8-understanding-git-rebase">chapter 8</a>, you learned about Git rebase. We then considered it mainly as a tool to combine changes introduced in different branches. Yet, as long as you haven't <code>push</code>ed your changes, using <code>rebase</code> on your own branch can be a very convenient way to rearrange your commit history.</p>
<p>For that, you would usually <a class="post-section-overview" href="#heading-how-to-rebase-on-a-single-branch">rebase on a single branch</a>, and use interactive rebase. Consider again this example covered in <a class="post-section-overview" href="#heading-chapter-8-understanding-git-rebase">chapter 8</a>, where I worked from <code>feature_branch_2</code>, and specifically edited the file <code>code.py</code>. I started by changing all strings to be wrapped by double quotes rather than single quotes:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_4-1.png" alt="Changing  into  in " width="600" height="400" loading="lazy">
<em>Changing <code>'</code> into <code>"</code> in <code>code.py</code></em></p>
<p>Then, I staged and committed:</p>
<pre><code class="lang-bash">git add code.py
git commit -m <span class="hljs-string">"Commit 17"</span>
</code></pre>
<p>I then decided to add a new function at the beginning of the file:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_5-1.png" alt="Adding the function " width="600" height="400" loading="lazy">
_Adding the function <code>another_feature</code>_</p>
<p>Again, I staged and committed:</p>
<pre><code class="lang-bash">git add code.py
git commit -m <span class="hljs-string">"Commit 18"</span>
</code></pre>
<p>And now I realized I actually forgot to change the single quotes to double quotes wrapping the <code>__main__</code> (as you might have noticed), so I did that too:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/code_py_6-1.png" alt="Changing  into " width="600" height="400" loading="lazy">
<em>Changing <code>'__main__'</code> into <code>"__main__"</code></em></p>
<p>Of course, I staged and committed this change:</p>
<pre><code class="lang-bash">git add code.py
git commit -m <span class="hljs-string">"Commit 19"</span>
</code></pre>
<p>Now, consider the history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/history_after_commit_19-1.png" alt="The commit history after introducing &quot;Commit 19&quot;" width="600" height="400" loading="lazy">
<em>The commit history after introducing "Commit 19"</em></p>
<p>As explained in <a class="post-section-overview" href="#heading-chapter-8-understanding-git-rebase">chapter 8</a>, I got to a state with two commits that are related to one another, "Commit 17" and "Commit 19" (turning <code>'</code>s into <code>"</code>s), but they are split by the unrelated "Commit 18" (where I added a new function).</p>
<p>This is a classic case where <code>git rebase</code> would come in handy, to undo the local changes before <code>push</code>ing a clean history.</p>
<p>Intuitively, I want to edit the history here:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/plan_edit_commits_17_18-1.png" alt="These are the commits I want to edit" width="600" height="400" loading="lazy">
<em>These are the commits I want to edit</em></p>
<p>I can <code>rebase</code> the history from "Commit 17" to "Commit 19", on top of "Commit 15". To do that:</p>
<pre><code class="lang-bash">git rebase --interactive --onto &lt;SHA_OF_COMMIT_15&gt; &lt;SHA_OF_COMMIT_15&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/rebase_onto_4-1.png" alt="Using  on a single branch" width="600" height="400" loading="lazy">
<em>Using <code>rebase --onto</code> on a single branch</em></p>
<p>This results in the following screen:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/interactive_rebase_4-1.png" alt="Interactive rebase" width="600" height="400" loading="lazy">
<em>Interactive rebase</em></p>
<p>So what would I do? I want to put "Commit 19" before "Commit 18", so it comes right after "Commit 17". I can go further and <code>squash</code> them together, like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/interactive_rebase_5-1.png" alt="Interactive rebase - changing the order of commit and squashing" width="600" height="400" loading="lazy">
<em>Interactive rebase - changing the order of commit and squashing</em></p>
<p>Now when I get prompted for a commit message, I can provide the message "Commit 17+19":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/interactive_rebase_6-1.png" alt="Providing a commit message" width="600" height="400" loading="lazy">
<em>Providing a commit message</em></p>
<p>And now, see our beautiful history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/rebase_onto_5-1.png" alt="The resulting history" width="600" height="400" loading="lazy">
<em>The resulting history</em></p>
<p>The syntax used above, <code>git rebase --interactive --onto &lt;COMMIT X&gt; &lt;COMMIT X&gt;</code> would be the most commonly used syntax by those who use <code>rebase</code> regularly. The state of mind these developers usually have is to create atomic commits while working, all the time, without being scared to change them later. Then, before <code>push</code>ing their changes, they would <code>rebase</code> the entire set of changes since the last <code>push</code>, and rearrange it so the history becomes coherent.</p>
<h3 id="heading-git-reflog"><code>git reflog</code></h3>
<p>Time to consider a more startling case.</p>
<p>Go back to "Commit 2.4":</p>
<pre><code class="lang-bash">git reset --hard &lt;SHA_OF_COMMIT_2_4&gt;
</code></pre>
<p>Get some work done, write some code, and add it to <code>love.txt</code>. Stage this change, and commit it:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">echo</span> lots of work &gt;&gt; love.txt
git add love.txt
git commit -m <span class="hljs-string">"Commit 3.2"</span>
</code></pre>
<p>(I'm using "Commit 3.2" to indicate that this is not the same commit as "Commit 3" we used when explaining <code>git revert</code>.)</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/reflog_commit_3-1.png" alt="Another commit" width="600" height="400" loading="lazy">
<em>Another commit - "Commit 3.2"</em></p>
<p>I did the same on my machine, and I used the <code>Up</code> arrow key on my keyboard to scroll back to previous commands, and then I hit <code>Enter</code>, and… Wow.</p>
<p>Whoops.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/reflog_commit_3_reset.png" alt="Did I just ?" width="600" height="400" loading="lazy">
<em>Did I just <code>git reset -- hard</code>?</em></p>
<p>Did I just use <code>git reset --hard</code>? 😨</p>
<p>What actually happened? As you learned in the <a class="post-section-overview" href="#heading-chapter-9-git-reset">previous chapter</a>, Git moved the pointer to <code>HEAD~1</code>, so the last commit, with all of my precious work, is not reachable from the current history. Git also removed all the changes from the staging area, and then matched the working dir to the state of the staging area.</p>
<p>That is, everything matches this state where my work is… gone.</p>
<p>Freak out time. Freaking out.</p>
<p>But, really, is there a reason to freak out? Not really… We're relaxed people. What do we do? Well, intuitively, is the commit really, really gone?</p>
<p>No. Why not? It still exists inside the internal database of Git.</p>
<p>If I only knew where that is, I would know the <code>SHA-1</code> value that identifies this commit, and we could restore it. I could even undo the undoing, and <code>reset</code> back to this commit.</p>
<p>Actually, the only thing I really need here is the <code>SHA-1</code> of the "deleted" commit.</p>
<p>Now the question is, how do I find it? Would <code>git log</code> be useful?</p>
<p>Well, not really. <code>git log</code> would go to <code>HEAD</code>, which points to <code>main</code>, which points to the parent commit of the commit we are looking for. Then, <code>git log</code> would trace back through the parent chain, which does not include the commit with my precious work.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/reflog_git_log.png" alt=" doesn't help in this case" width="600" height="400" loading="lazy">
<em><code>git log</code> doesn't help in this case</em></p>
<p>Thankfully, the very smart people who created Git also created a backup plan for us, and that is called the <code>reflog</code>.</p>
<p>While you work with Git, whenever you change <code>HEAD</code>, which you can do by using <code>git reset</code>, but also other commands like <code>git switch</code> or <code>git checkout</code>, Git adds an entry to the <code>reflog</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reflog.png" alt=" shows us where  was" width="600" height="400" loading="lazy">
<em><code>git reflog</code> shows us where <code>HEAD</code> was</em></p>
<p>We found our commit! It's the one starting with <code>0fb929e</code>.</p>
<p>We can also relate to it by its "nickname" - <code>HEAD@{1}</code>. Similar to the way Git uses <code>HEAD~1</code> to get to the first parent of <code>HEAD</code>, and <code>HEAD~2</code> to refer to the second parent of <code>HEAD</code> and so on, Git uses <code>HEAD@{1}</code> to refer to the first <em>reflog</em> parent of <code>HEAD</code>, that is, where <code>HEAD</code> pointed to in the previous step.</p>
<p>We can also ask <code>git rev-parse</code> to show us its value:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/reflog_revparse.png" alt="Using " width="600" height="400" loading="lazy">
<em>Using <code>git rev-parse HEAD@{1}</code></em></p>
<p>Note: In case you are using Windows, you may need to wrap it with quotation marks - like so:</p>
<pre><code class="lang-bash">git rev-parse <span class="hljs-string">"HEAD@{1}"</span>
</code></pre>
<p>Another way to view the <code>reflog</code> is by using <code>git log -g</code>, which asks <code>git log</code> to actually consider the <code>reflog</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_g.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git log -g</code></em></p>
<p>You can see in the output of <code>git log -g</code> that the <code>reflog</code>'s entry <code>HEAD@{0}</code>, just like <code>HEAD</code>, points to <code>main</code>, which points to "Commit 2". But the parent of that entry in the <code>reflog</code> points to "Commit 3".</p>
<p>So to get back to "Commit 3", you can just use <code>git reset --hard HEAD@{1}</code> (or the <code>SHA-1</code> value of "Commit 3"):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reflog_reset.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git reset --hard HEAD@{1}</code></em></p>
<p>And now, if you <code>git log</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_2.png" alt="Our history is back!!!" width="600" height="400" loading="lazy">
<em>Our history is back!!!</em></p>
<p>We saved the day!</p>
<p>What would happen if I used this command again? And ran <code>git reset --hard HEAD@{1}</code>?</p>
<p>Git would set <code>HEAD</code> to where <code>HEAD</code> was pointing before the last <code>reset</code>, meaning to "Commit 2". We can keep going all day:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_reset_again.png" alt=" again" width="600" height="400" loading="lazy">
<em><code>git reset --hard</code> again</em></p>
<h3 id="heading-recap-additional-tools-for-undoing-changes">Recap - Additional Tools for Undoing Changes</h3>
<p>In the previous chapter, you learned how to use <code>git reset</code> to undo changes.</p>
<p>In this chapter, you extended your toolbox for undoing changes in Git with a few new commands:</p>
<ul>
<li><code>git commit --amend</code> - which "overrides" the last commit with the stage of the index. Mostly useful when you just committed something and want to modify that last commit.</li>
<li><code>git revert</code> - which creates a new commit, that reverts a past commit by adding a new commit to the history with the reversed changes. Useful especially when the "faulty" commit has already been pushed to the remote.</li>
<li><code>git rebase</code> - which you already know from <a class="post-section-overview" href="#heading-chapter-8-understanding-git-rebase">chapter 8</a>, and is useful for rewriting the history of multiple commits, especially before pushing them.</li>
<li><code>git reflog</code> (and <code>git log -g</code>) - which tracks all changes to <code>HEAD</code>, so you might find the SHA-1 value of a commit you need to get back to.</li>
</ul>
<p>The most important tool, even more important than the tools I just listed, is to whiteboard the current situation vs the desired one. Trust me on this, it will make every situation seem less daunting and the solution more clear.</p>
<p>There are additional tools that allow you to reverse changes in Git (I will provide links in the <a class="post-section-overview" href="#heading-additional-references-by-part">appendix</a>), but the collection of tools covered here should prepare you to tackle any challenge with confidence.</p>
<h2 id="heading-chapter-11-exercises">Chapter 11 - Exercises</h2>
<p>This chapter includes a few exercises to deepen your understanding of the tools you learned in Part 3. The full version of this book also includes detailed solutions for each.</p>
<p>The exercises are found on this repository:</p>
<p><a target="_blank" href="https://github.com/Omerr/undo-exercises.git">https://github.com/Omerr/undo-exercises.git</a></p>
<p>Each exercise exists on a branch with the name <code>exercise_XX</code>, so Exercise 1 is found on branch <code>exercise_01</code>, Exercise 2 is found on branch <code>exercise_02</code> and so on.</p>
<p>Note: As explained in previous chapters, if you work with commits that can be found on a remote server (which you are in this case, as you are using my repository "undo-exercises"), you should probably use <code>git revert</code> instead of <code>git reset</code>. Similar to <code>git rebase</code>, the command <code>git reset</code> also rewrites history - and thus you should refrain from using it on commits that others may have relied on. </p>
<p>For the purposes of these exercises, you can assume no one else has cloned or pulled code from the remote repository. Just remember - in real life, you should probably use <code>git revert</code> instead of commands that rewrite history in such cases.</p>
<h3 id="heading-exercise-1">Exercise 1</h3>
<p>On branch <code>exercise_01</code>, consider the file <code>hello.txt</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/ex_01_1.png" alt="The file " width="600" height="400" loading="lazy">
<em>The file <code>hello.txt</code></em></p>
<p>This file includes a typo (in the last character). Find the commit that introduced this typo.</p>
<h4 id="heading-exercise-1a">Exercise (1a)</h4>
<p>Remove this commit from the reachable history using <code>git reset</code> (with the right arguments), fix the typo, and commit again. Consider your history.</p>
<p>Revert to the previous state.</p>
<h4 id="heading-exercise-1b">Exercise (1b)</h4>
<p>Remove the faulty commit using <code>git commit --amend</code>, and get to the same state of the history as in the end of exercise (1a).</p>
<p>Revert to the previous state.</p>
<h4 id="heading-exercise-1c">Exercise (1c)</h4>
<p><code>revert</code> the faulty commit using <code>git revert</code> and fix the typo. Consider your history.</p>
<p>Revert to the previous state.</p>
<h4 id="heading-exercise-1d">Exercise (1d)</h4>
<p>Using <code>git rebase</code>, get to the same state as in the end of exercise (1a).</p>
<h3 id="heading-exercise-2">Exercise 2</h3>
<p>Switch to <code>exercise_02</code>, and consider the contents of <code>exercise_02.txt</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/ex_02_1.png" alt="The contents of " width="600" height="400" loading="lazy">
_The contents of <code>exercise_02.txt</code>_</p>
<p>A simple file, with one character at each line.</p>
<p>Consider the history (using <code>git lol</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/ex_02_2.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git lol</code></em></p>
<p>Oh my. Each character was introduced in a separate commit. That doesn't make any sense!</p>
<p>Use the tools you've acquired to create a history where the creation of <code>exercise_02.txt</code> is all done in a single commit.</p>
<h3 id="heading-exercise-3">Exercise 3</h3>
<p>Consider the history on branch <code>exercise_03</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/ex_03_1.png" alt="The history on " width="600" height="400" loading="lazy">
_The history on <code>exercise_03</code>_</p>
<p>This seems like a mess. You will notice that:</p>
<ul>
<li>The order is skewed. We need "Commit 1" to be the earliest commit on this branch, and have "Initial Commit" as its parent, followed by "Commit 2" and so on.</li>
<li>We shouldn't have "Commit 2a" and "Commit 2b", or "Commit 4a" and "Commit 4b" - these two pairs need to be combined into a single commit each - "Commit 2" and "Commit 4".</li>
<li>There is a typo on the commit message of "Commit 1", it should not have 3 <code>m</code>s.</li>
</ul>
<p>Fix these issues, but rely on the changes of each original commit. The resulting history should look like so:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/ex_03_2.png" alt="The desired history" width="600" height="400" loading="lazy">
<em>The desired history</em></p>
<h3 id="heading-exercise-4">Exercise 4</h3>
<p>This exercise actually consists of three branches: <code>exercise_04</code>, <code>exercise_04_a</code>, and <code>exercise_04_b</code>.</p>
<p>To see the history of these branches without others, use the following syntax:</p>
<pre><code class="lang-bash">git lol --branches=<span class="hljs-string">"exercise_04*"</span>
</code></pre>
<p>The result is:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/ex_04_1.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git lol --branches="exercise_04*"</code>_</p>
<p>Your goal is to make <code>exercise_04_b</code> independent of <code>exercise_04_a</code>. That is, get to this history:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/ex_04_2.png" alt="The desired history" width="600" height="400" loading="lazy">
<em>The desired history</em></p>
<p><strong>Good luck!</strong></p>
<h1 id="heading-part-4-amazing-and-useful-git-tools">Part 4 - Amazing and Useful Git Tools</h1>
<p>Git has lots of commands, and these commands have so many options and arguments. I could try to cover them all (though they do change over time), but I don't see a point in that. You should probably know a subset of these commands really well, those that you use regularly. Then, you can always search for a specific command to perform a task at hand.</p>
<p>This part relies on the basics you acquired in the previous parts, and covers specific commands and options that you may find useful. Given your understanding of how Git works, having these small tools can make you a real pro in Gitting things done.</p>
<h2 id="heading-chapter-12-git-log">Chapter 12 - Git Log</h2>
<p>You used <code>git log</code> many times across different chapters, and you had probably used it many times before reading this book.</p>
<p>Most developers use <code>git log</code>, few use it effectively. In this chapter you will learn useful tweaks for making the most of <code>git log</code>. Once you feel comfortable with the different switches of this command, it will be a game changer in your day to day work with Git.</p>
<p>Thinking about it, <code>git log</code> encompasses the essence of every version control system - that is, to record changes in versions. You record versions so that you can consider the history of your project - perhaps revert or apply specific changes, prefer to switch to a different point in time and test things there. Perhaps you would like to know who contributed a certain piece of code or when they did that.</p>
<p>While <code>git</code> does preserve this information by using commit objects, that also point to their parent commits, and references to commit objects (such as branches or <code>HEAD</code>), this storing of versions is not enough. Without being able to find the relevant commit you would like to consider, or gather the relevant information about it, having this data stored is pretty useless.</p>
<p>You can think of your commit objects as different books that pile up in a huge stack, or in a library, filling long shelves. The information you might need is in these books, but if you don't have an index - a way to know in which book the information you seek lies, or where this book is located within the library - you wouldn't be able to make much use of it. <code>git log</code> is this indexing of your library - it's a way to find the relevant commits and the information about them.</p>
<p>The useful arguments for <code>git log</code> that you will learn in this chapter either format how commits are displayed in the log, or filter specific commits.</p>
<p><code>git lol</code>, an alias which I have used throughout the book, uses some of these switches, as I will demonstrate. Feel free to tweak this alias (or create another from scratch) after reading this chapter.</p>
<p>As in other chapters, the goal is not to provide a complete reference, therefore I will not provide <em>all</em> different switches of <code>git log</code>. I will focus on the switches I believe you will find useful.</p>
<h3 id="heading-filtering-commits">Filtering Commits</h3>
<p>Consider the default output of <code>git log</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_1.png" alt="The output of  without additional switches" width="600" height="400" loading="lazy">
<em>The output of <code>git log</code> without additional switches</em></p>
<p>The log starts from <code>HEAD</code>, and follows the parent chain.</p>
<h4 id="heading-commits-not-reachable-from">Commits (Not) Reachable From...</h4>
<p>When you write <code>git log &lt;revision&gt;</code>, <code>git log</code> will include all entries reachable from <code>&lt;revision&gt;</code>. By "reachable", I refer to reachable by following the parent chain. So running <code>git log</code> without any arguments is equivalent to running <code>git log HEAD</code>.</p>
<p>You can specify multiple revisions for <code>git log</code> - if you write <code>git log branch_1 branch_2</code>, you ask <code>git log</code> to include every commit that is reachable from <code>branch_1</code> or <code>branch_2</code> (or both).</p>
<p><code>git log</code> will <strong>exclude</strong> any commits that are reachable from revisions preceded by a <code>^</code>.</p>
<p>For example, the following command:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> branch_1 ^branch_2
</code></pre>
<p>asks <code>git log</code> to include every commit that is reachable from <code>branch_1</code>, but not those reachable from <code>branch_2</code>.</p>
<p>Consider the history when I use <code>git log feature_branch_1</code> on this repo:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_2-1.png" alt="Image" width="600" height="400" loading="lazy">
_<code>git log feature_branch_1</code>_</p>
<p>The history includes all commits reachable by <code>feature_branch_1</code>. Since this branch "branched off" <code>main</code> (that is, "Commit 12", which <code>main</code> points to, is reachable from the parent chain) - the log also includes the commits reachable from <code>main</code>.</p>
<p>What would happen if I ran this command?</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> feature_branch_1 ^main
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_3.png" alt="Image" width="600" height="400" loading="lazy">
_<code>git log feature_branch_1 ^main</code>_</p>
<p>Indeed, <code>git log</code> outputs only "Commit 13" and "Commit 16", which are reachable from <code>feature_branch_1</code> but not from <code>main</code>.</p>
<h4 id="heading-git-log-all"><code>git log --all</code></h4>
<p>To follow commits that are reachable from any named reference or (any refs in <code>refs/</code>) or <code>HEAD</code>.</p>
<h4 id="heading-by-author">By Author</h4>
<p>If you know you are looking for a commit that a specific person has authored, you can filter these commits by using that user's name or email, like so:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --author=<span class="hljs-string">"Name"</span>
</code></pre>
<p>You can use regular expressions to look for author names that match a specific pattern, for example:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --author=<span class="hljs-string">"John\|Jane"</span>
</code></pre>
<p>will filter commits authored by either John or Jane.</p>
<h4 id="heading-by-date">By Date</h4>
<p>When you know that the change you are looking for has been committed within a specific timeframe, you can use <code>--before</code> or <code>--after</code> to filter commits from that timeframe.</p>
<p>For example, to get all commits introduced after April 12th, 2023 (inclusive), use:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --after=<span class="hljs-string">"2023-04-12"</span>
</code></pre>
<h4 id="heading-by-paths">By Paths</h4>
<p>You can ask <code>git log</code> to only show commits where <em>changes</em> to files in specific paths have been introduced. Notice that this does not mean any commit that points to a tree that includes the files in question, but rather that if we compute the difference between the commit in question and its parent, we would see that at least one of the paths has been modified.</p>
<p>For example, you can use:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --all -- 1.py
</code></pre>
<p>to find all commits that are reachable from any named pointer, or <code>HEAD</code>, and introduce a change to <code>1.py</code>. You can specify multiple paths:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --all -- 1.py 2.py
</code></pre>
<p>The previous command will make <code>git log</code> include reachable commits that introduced a change to <code>1.py</code> or <code>2.py</code> (or both).</p>
<p>You can also use a glob pattern, for example:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> -- *.py
</code></pre>
<p>will include commits reachable from <code>HEAD</code> that include a change to any file in the root directory whose name ends with a <code>.py</code>. To look for any file whose name ends with <code>.py</code>, you can use:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> -- **/*.py
</code></pre>
<h4 id="heading-by-commit-message">By Commit Message</h4>
<p>If you know the commit message (or parts of it) of the commit you are searching, you can use the <code>--grep</code> switch for "git log", for example:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --grep=<span class="hljs-string">"Commit 12"</span>
</code></pre>
<p>yields back the commit with the message "Commit 12".</p>
<h4 id="heading-by-diff-content">By Diff Content</h4>
<p>This one is super useful, and it saved me countless times. By using <code>git log -S</code>, you can search for commits that introduce or remove a particular line of source code. </p>
<p>This comes in handy, for example, when you know you have created something in the repo, but you don't know where it is now. You can't find it anywhere on your filesystem (it's not in <code>HEAD</code>), and you know it must be there - lurking somewhere in this library (bunch of commits) that you have.</p>
<p>Say I remember I wrote a line with the text <code>Git is awesome</code>, but I can't find it now. I could run:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --all -S<span class="hljs-string">"Git is awesome"</span>
</code></pre>
<p>Notice I used <code>--all</code> to avoid restraining myself to commits reachable from <code>HEAD</code>.</p>
<p>You can also search for a regular expression, using <code>-G</code>:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --all -G<span class="hljs-string">"Git .* awesome"</span>
</code></pre>
<h3 id="heading-formatting-log">Formatting Log</h3>
<p>Consider the default output of <code>git log</code> again:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_1-1.png" alt="The output of  without additional switches" width="600" height="400" loading="lazy">
<em>The output of <code>git log</code> without additional switches</em></p>
<p>The log starts from <code>HEAD</code>, and follows the parent chain.</p>
<p>Each log entry begins with a line starting with <code>commit</code> and then the SHA-1 of the commit, perhaps followed by additional pointers that point to this commit.<br>It is then followed by the author, date, and commit message.</p>
<h4 id="heading-oneline"><code>--oneline</code></h4>
<p>The main difficulty with the default output of <code>git log</code> is that it is hard to understand a history with more than a few commits, as you simply don't see them all. </p>
<p>In the output of <code>git log</code> shown before, only four commit objects appeared on my screen. Using <code>git log --oneline</code> provides a more concise view, showing the SHA-1 of the commit, next to its message, and named references if relevant:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_5.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git log --oneline</code></em></p>
<p>If you wish to omit the named references, you can add the <code>--no-decorate</code> switch:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_6.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git log --oneline --no-decorate</code></em></p>
<p>To explicitly ask for <code>git log</code> to show decorations, you can use <code>git log --decorate</code>.</p>
<h4 id="heading-graph"><code>--graph</code></h4>
<p><code>git log --oneline</code> shows a compact representation. That is great when we have a linear history, perhaps on a single branch. But what happens when we have multiple branches, that may diverge from one another?</p>
<p>Consider the output of the following command on my repository:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --oneline feature_branch_1 feature_branch_2
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_7.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git log --oneline feature_branch_1 feature_branch_2</code>_</p>
<p><code>git log</code> outputs any commit reachable by <code>feature_branch_1</code>, <code>feature_branch_2</code>, or both. But what does the history look like? Did <code>feature_branch_2</code> diverge from <code>feature_branch_1</code>? Or did it diverge from <code>main</code>? It is impossible to tell from this view. </p>
<p>This is where <code>--graph</code> comes in handy, drawing an ASCII graph representing the branch structure of the commit history. If we add this option to the previous command:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_8.png" alt="The output of " width="600" height="400" loading="lazy">
_The output of <code>git log --oneline --graph feature_branch_1 feature_branch_2</code>_</p>
<p>You can actually <em>see</em> that <code>feature_branch_1</code> branched from <code>main</code> (as "Commit 12", <code>main</code>, is the parent of "Commit 13"), and also that <code>feature_branch_2</code> branched from <code>main</code> (as the parent of "Commit 14" is also "Commit 12").</p>
<p>The <code>*</code> symbol tells us which branch a certain commit is "on", so you can know for sure that "Commit 13" is on <code>feature_branch_1</code>, and not <code>feature_branch_2</code>.</p>
<h4 id="heading-prettyformat"><code>--pretty=format</code></h4>
<p>The above result is already very useful! Yet, it lacks a few things. We don't know the author or the time of the commit. These two information details were included in the default output of <code>git log</code> which was very long. Perhaps we can add them in a more compact way?</p>
<p>By using <code>--pretty=format:</code>, you can display the information of each commit in various ways using <code>printf</code>-style placeholders.</p>
<p>In the following command, the <code>%s</code>, <code>%an</code> and <code>%cd</code> placeholders are replaced by the commit's subject (message), author name, and the commit's date, respectively.</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --oneline --graph feature_branch_1 feature_branch_2 --pretty=format:<span class="hljs-string">"%s (%an) [%cd]"</span>
</code></pre>
<p>The output looks like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_9.png" alt="Image" width="600" height="400" loading="lazy">
_<code>git log --oneline --graph feature_branch_1 feature_branch_2 --pretty=format:"%s (%an) [%cd]</code>_</p>
<p>That's useful, but not really great to look at. We can then use other formatting tricks, specifically <code>%C(color)</code> that will switch the color to <code>color</code>, until reaching a <code>%Creset</code> that resets the color. To make the author name's yellow, you can use:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --oneline --graph feature_branch_1 feature_branch_2 --pretty=format:<span class="hljs-string">"%s %C(yellow)(%an)%Creset [%cd]"</span>
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_10.png" alt="Image" width="600" height="400" loading="lazy">
_<code>git log --oneline --graph feature_branch_1 feature_branch_2 --pretty=format:"%s %C(yellow)(%an)%Creset [%cd]"</code>_</p>
<p>For some colors, like <code>red</code> or <code>green</code>, it is unnecessary to include the parenthesis, so <code>Cred</code> is enough.</p>
<h4 id="heading-how-is-git-lol-structured">How is <code>git lol</code> Structured?</h4>
<p>When I run <code>git lol</code>, it actually executes the following:</p>
<p><code>git log --graph --pretty=format:'%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&lt;%an&gt;%Creset' --abbrev-commit</code></p>
<p>Can you take this bit by bit?</p>
<p>You already know <code>--graph</code>, which makes the output include an ASCII graph.</p>
<p><code>--abbrev-commit</code> uses a short prefix from the full SHA-1 of the commit (in my configuration, the first seven characters).</p>
<p>The rest is just coloring of various details about the commit:</p>
<pre><code class="lang-bash">git lol --all
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_log_11.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git lol --all</code></em></p>
<p>I like this output because I find it clear. It gives me the information I need, with enough coloring so that every detail stands out without hurting my eyes. But if you prefer other information, other colors, a different order, or anything else - go ahead and tweak it to your liking.</p>
<h3 id="heading-setting-an-alias">Setting an alias</h3>
<p>As you know, I set <code>git lol</code> as an alias - that is, when I run <code>git lol</code>, it executes the long command I provided previously.</p>
<p>How can you create an alias in Git?</p>
<p>The easiest way is to use <code>git alias</code>, like so:</p>
<pre><code class="lang-bash">git config --global alias.co checkout
</code></pre>
<p>This command sets <code>co</code> to be an alias for the command <code>checkout</code>, so you can use <code>git co main</code> instead of <code>git checkout main</code>.</p>
<p>To define <code>git lol</code> as an alias, you can use:</p>
<pre><code class="lang-bash">git config --global alias.lol <span class="hljs-string">'log --graph --pretty=format:'</span>%Cred%h%Creset -%C(yellow)%d%Creset %s %Cgreen(%cr) %C(bold blue)&lt;%an&gt;%Creset<span class="hljs-string">' --abbrev-commit'</span>
</code></pre>
<h2 id="heading-chapter-13-git-bisect">Chapter 13 - Git Bisect</h2>
<p>Oops.</p>
<p>I have a bug.</p>
<p>Yes, that happens some times, to all of us. Something in my system is broken, and I can't tell why. I have been debugging for a while, but the solution is not clear.</p>
<p>I can tell that two weeks ago, this didn't happen. Luckily for me, I have been using Git (obviously, I know...), so I can go back in time and test a past version of my code. Indeed, in this version - everything worked fine.</p>
<p>But... I have made many changes in these two weeks. Alas, not just me - my entire team has contributed commits that add, delete, or modify parts of the code base. Where do I begin? Should I go over every change introduced in those two weeks?</p>
<p>Enter - <code>git bisect</code>.</p>
<p>The goal of <code>git bisect</code> is help you find the commit where a bug was introduced, in an effective manner.</p>
<h3 id="heading-how-does-git-bisect-work">How Does <code>git bisect</code> Work?</h3>
<p><code>git bisect</code> first asks you to mark one commit as "bad" (where the bug occurs), and another commit as "good" (one without the bug). Then, it checks out a commit halfway between these two commits, and then asks you to identify the commit as either "good" or "bad". This process is repeated until you find the first "bad" commit.</p>
<p>The key here is using binary search - by looking at the halfway point and deciding if it is the new top or bottom of the list of commits, you can find the right commit efficiently. Even if you have 10,000 commits to hunt through, it only takes a maximum of 13 steps to find the first commit that introduced the bug.</p>
<h3 id="heading-git-bisect-example"><code>git bisect</code> Example</h3>
<p>For this example, I will use the repository on <a target="_blank" href="https://github.com/Omerr/bisect-exercise.git">https://github.com/Omerr/bisect-exercise.git</a>. To create it, I adapted the open source repository <a target="_blank" href="https://github.com/bast/git-bisect-exercise">https://github.com/bast/git-bisect-exercise</a> (according to its license).</p>
<p>In this repository, we have a single python file that is used to compute the value of pi (which is approximately <code>3.14</code>). If you run <code>python3 get_pi.py</code> on <code>main</code>, however, you will get a wrong result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/bisect_1.png" alt="A wrong result, we have a bug" width="600" height="400" loading="lazy">
<em>A wrong result, we have a bug</em></p>
<p>This branch consists of more than 500 commits.</p>
<p>Find the first commit on this branch by using:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">log</span> --oneline | tail -n 1
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/bisect_2.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git log --oneline | tail -n 1</code></em></p>
<p>If you <code>checkout</code> to this commit and run <code>python3 get_pi.py</code> again, the result is correct:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/commit_1_pi.png" alt="From the first commit, the result is valid" width="600" height="400" loading="lazy">
<em>From the first commit, the result is valid</em></p>
<p>So somewhere between <code>HEAD</code> and commit <code>f0ea950</code>, a change was introduced that resulted in this wrong output.</p>
<p>To find it using <code>git bisect</code>, <code>start</code> the bisect process, and mark this commit as "good":</p>
<pre><code class="lang-bash">git bisect start
git bisect good
</code></pre>
<p>By default, <code>git bisect good</code> would take <code>HEAD</code> as the "good" commit. To mark <code>main</code> as "bad", you can use <code>git bisect bad main</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/bisect_3.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git bisect bad main</code></em></p>
<p><code>git bisect</code> checked out commit number <code>251</code>, the "middle point" of <code>main</code> branch. Does the state in this commit produce the right or wrong output?</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/bisect_4.png" alt="Trying again..." width="600" height="400" loading="lazy">
<em>Trying again...</em></p>
<p>We still get the wrong output, which means we can discard commits <code>252</code> through <code>500</code> (and additional commits after that), and narrow our search to commits <code>2</code> through <code>251</code>. Mark this as <code>bad</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/bisect_5.png" alt="Mark as " width="600" height="400" loading="lazy">
<em>Mark as <code>bad</code></em></p>
<p><code>git bisect</code> checked out the "middle" commit (number <code>126</code>), and running the code again results in the right answer! This means that this commit is "good", and that the first "bad" commit is somewhere between <code>127</code> and <code>251</code>. Mark it as "good":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/bisect_6.png" alt="Mark as " width="600" height="400" loading="lazy">
<em>Mark as <code>good</code></em></p>
<p>Nice, <code>git bisect</code> takes us to commit <code>188</code>, as this is the "middle" commit between <code>127</code> and <code>251</code>. By running the code again, you can see that the result is wrong, so this is actually a "bad" commit, which means the first faulty commit is somewhere between <code>127</code> and <code>188</code>. As you can see, <code>git bisect</code> narrows down the search space by half on each iteration.</p>
<p>Come on, now it's your turn - keep going from here! Test the result of <code>python3 get_pi.py</code> and use <code>git bisect good</code> or <code>git bisect bad</code> to mark the commit accordingly. What is the faulty commit?</p>
<p>When you are done, use <code>git bisect reset</code> to stop the bisect process.</p>
<h3 id="heading-automatic-git-bisect">Automatic <code>git bisect</code></h3>
<p>In the previous example, you could simply run <code>python3 get_pi.py</code> and check the result. Other times, the process of validating whether a certain commit is "good" or "bad" can be tricky, error prone, or just time consuming. </p>
<p>It is possible to automate the process of <code>git bisect</code> by creating code that would be executed on each iteration, returning <code>0</code> when the current commit is "good", and a value between <code>1-127</code> (inclusive), except <code>125</code>, if it should be considered "bad".</p>
<p>The syntax is:</p>
<pre><code class="lang-bash">git bisect run my_script arguments
</code></pre>
<p>As this book is not about programming and doesn't assume you know a specific programming language, I will not show an example of implementing <code>my_script</code>. The <code>README.md</code> file in the repository used in this chapter (<a target="_blank" href="https://github.com/Omerr/bisect-exercise.git">https://github.com/Omerr/bisect-exercise.git</a>) includes an example for a script that you can run with <code>git bisect run</code> to automatically find the faulty commit for the previous example.</p>
<h2 id="heading-chapter-14-other-useful-commands">Chapter 14 - Other Useful Commands</h2>
<p>This chapter highlights a few commands that had have already been mentioned in previous chapters. I am putting them here together so that you can come back to them as a reference when needed.</p>
<h3 id="heading-git-cherry-pick"><code>git cherry-pick</code></h3>
<p>Introduced in <a class="post-section-overview" href="#heading-chapter-8-understanding-git-rebase">chapter 8</a>, this command takes a given commit, computes the <strong>patch</strong> this commit introduces by computing the difference between the parent's commit and the commit itself, and then <code>cherry-pick</code> "replays" this difference. It is like "copy-pasting" a commit, that is, the diff this commit introduced.</p>
<p>In <a class="post-section-overview" href="#heading-chapter-8-understanding-git-rebase">chapter 8</a> we considered the difference introduced by "Commit 5" (using <code>git diff main &lt;SHA_OF_COMMIT_5&gt;</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main_commit_5-1.png" alt="Running  to observe the patch introduced by &quot;Commit 5&quot;" width="600" height="400" loading="lazy">
<em>Running <code>git diff</code> to observe the patch introduced by "Commit 5"</em></p>
<p>You can see that in this commit, John started working on a song called "Lucy in the Sky with Diamonds":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_diff_main_commit_5_output-1.png" alt="The output of  - the patch introduced by &quot;Commit 5&quot;" width="600" height="400" loading="lazy">
<em>The output of <code>git diff</code> - the patch introduced by "Commit 5"</em></p>
<p>As a reminder, you can also use the command <code>git show</code> to get the same output:</p>
<pre><code class="lang-bash">git show &lt;SHA_OF_COMMIT_5&gt;
</code></pre>
<p>Now, if you <code>cherry-pick</code> this commit, you will introduce <em>this change</em> specifically, on the active branch. You can switch to <code>main</code> branch:</p>
<pre><code class="lang-bash">git checkout main (or git switch main)
</code></pre>
<p>And create another branch:</p>
<pre><code class="lang-bash">git checkout -b my_branch (or git switch -c my_branch)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/create_my_branch-1.png" alt="Creating  that branches from " width="600" height="400" loading="lazy">
_Creating <code>my_branch</code> that branches from <code>main</code>_</p>
<p>Next, <code>cherry-pick</code> "Commit 5":</p>
<pre><code class="lang-bash">git cherry-pick &lt;SHA_OF_COMMIT_5&gt;
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/cherry_pick_commit_5-1.png" alt="Using  to apply the changes introduced in &quot;Commit 5&quot; onto " width="600" height="400" loading="lazy">
<em>Using <code>cherry-pick</code> to apply the changes introduced in "Commit 5" onto <code>main</code></em></p>
<p>Consider the log (output of <code>git lol</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_lol_commit_5-1.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git lol</code></em></p>
<p>It seems like you <em>copy-pasted</em> "Commit 5". Remember that even though it has the same commit message, and introduces the same changes, and even points to the same tree object as the original "Commit 5" in this case - it is still a different commit object, as it was created with a different timestamp.</p>
<p>Looking at the changes, using <code>git show HEAD</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/git_show_HEAD-3.png" alt="The output of " width="600" height="400" loading="lazy">
<em>The output of <code>git show HEAD</code></em></p>
<p>They are the same as "Commit 5"'s.</p>
<h3 id="heading-git-revert-1"><code>git revert</code></h3>
<p><code>git revert</code> is essentially the reverse of <code>git cherry-pick</code>, introduced in <a class="post-section-overview" href="#heading-chapter-10-additional-tools-for-undoing-changes">chapter 10</a>. This command takes the commit you're providing it with and computes the diff from its parent commit, just like <code>git cherry-pick</code>, but this time, it computes the <em>reverse</em> changes. That is, if in the specified commit you added a line, the reverse would delete the line, and vice versa.</p>
<h3 id="heading-git-add-p"><code>git add -p</code></h3>
<p>Staging changes is an integral part of introducing changes to Git. Sometimes, you wish to stage all changes together (with <code>git add .</code>), or perhaps stage all changes of a specific file (using <code>git add &lt;file_path&gt;</code>). Yet there are times where it would be convenient to stage only certain parts of modified files.</p>
<p>In <a target="_blank" href="https://www.freecodecamp.org/news/p/f7b355ea-3f22-4613-8218-e95c67779d9f/chapter-6-diffs-and-patches">chapter 6</a>, we introduced <code>git add -p</code>. This command allows you to stage certain parts of files, by splitting them into hunks (<code>p</code> stands for <code>patch</code>). For example, say you have this file, <code>my_file.py</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/my_file_py_1.png" alt="Image" width="600" height="400" loading="lazy">
_<code>my_file.py</code>_</p>
<p>You then modify this file - by changing text within <code>function_1</code>, and also adding a new function, <code>function_5</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/my_file_py_2.png" alt=" after the changes" width="600" height="400" loading="lazy">
_<code>my_file.py</code> after the changes_</p>
<p>If you used <code>git add my_file.py</code> at this point, you would stage both of these changes together. In case you want to separate them into different commits, you could use <code>git add -p</code>, which splits these two changes and asks you about each one as a standalone hunk:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/add_p_1.png" alt="Image" width="600" height="400" loading="lazy">
<em><code>git add -p</code></em></p>
<p>By typing <code>?</code>, you can see what the different options stand for:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/add_p_2.png" alt="Using a  to get a description of the different options" width="600" height="400" loading="lazy">
<em>Using a <code>?</code> to get a description of the different options</em></p>
<p>In this case, say we only want to stage the change introducing <code>function_5</code>. We do not want to stage the change of <code>function_1</code>, so we select <code>n</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/12/add_p_3.png" alt="Not staging the change to " width="600" height="400" loading="lazy">
_Not staging the change to <code>function_1</code>_</p>
<p>Next, we are prompted for the second change - the one introducing <code>function_5</code>. We want to stage this hunk indeed, to can do so we can type <code>y</code>.</p>
<h1 id="heading-summary">Summary</h1>
<p>Well, this was FUN!</p>
<p>Can you believe how much you have learned?</p>
<p>In <strong>Part 1</strong> you learned about - blobs, trees, and commits.</p>
<p>You then learned about <strong>branches</strong>, seeing that they are nothing but a named reference to a commit.</p>
<p>You learned the process of recording changes in Git, and that it involves the <strong>working directory</strong>, the <strong>staging area (index)</strong>, and the <strong>repository</strong>.</p>
<p>Then - you created a new repository from scratch, by using <code>echo</code> and low-level commands such as <code>git hash-object</code>. You created a blob, a tree, and a commit object pointing to that tree.</p>
<p>In <strong>Part 2</strong> you learned about branching and integrating changes in Git.</p>
<p>You learned what a <strong>diff</strong> is, and the difference between a diff and a <strong>patch</strong>. You also learned how the output of <code>git diff</code> is constructed.</p>
<p>Then, you got an extensive overview of merging with Git, specifically understanding the three-way merge algorithm. You understood when <strong>merging conflicts</strong> occur, when Git can resolve them automatically, and how to resolve them manually when needed.</p>
<p>You saw that <code>git rebase</code> is powerful - but also that it is quite simple once you understand what it does. You understood the differences between merging and rebasing, and when you should use each.</p>
<p>In <strong>Part 3</strong> you learned how to <strong>undo changes</strong> in Git - especially when things go wrong. You learned how to use a bunch of tools, like <code>git reset</code>, <code>git commit --amend</code>, <code>git revert</code>, <code>git reflog</code> (and <code>git log -g</code>).</p>
<p>The most important tool, even more important than the tools I just listed, is to whiteboard the current situation vs the desired one. Trust me on this, it will make every situation seem less daunting and the solution more clear.</p>
<p>In <strong>Part 4</strong> you acquired additional powerful tools, like different switches of <code>git log</code>, <code>git bisect</code>, <code>git cherry-pick</code>, <code>git revert</code> and <code>git add -p</code>.</p>
<p>Wow, you should be proud of yourself!</p>
<h3 id="heading-a-message-from-me-to-you">A Message From Me to You</h3>
<p>Indeed, this was fun, but all things must pass. You finished reading this book, but this doesn't mean your learning journey ends here.</p>
<p>What you have acquired, more than any specific tool, is intuition and understanding of how Git operates, and how to think about various operations in Git. Keep researching, reading, and using Git. I am sure you will be able to teach me something new, and by all means - please do.</p>
<p>If you liked this book, please share it with more people.</p>
<p>If you want to read more of my Git articles and handbooks, here they are:</p>
<ol>
<li><a target="_blank" href="https://www.freecodecamp.org/news/git-rebase-handbook/">The Git Rebase Handbook</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/the-definitive-guide-to-git-merge/">The Git Merge Handbook</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/git-diff-and-patch/">The Git Diff and Patch Handbook</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/git-internals-objects-branches-create-repo/">Git Internals - Objects, Branches, and How to Create a Repo</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/save-the-day-with-git-reset/">Git Reset Command Explained</a></li>
</ol>
<h3 id="heading-acknowledgements">Acknowledgements</h3>
<p>Many people helped make this book the best it can be. Among them, I was lucky to have many beta readers that provided me with feedback so that I can improve the book. Specifically, I would like to thank Jason S. Shapiro, Anna Łapińska, C. Bruce Hilbert, and Jonathon McKitrick for their thorough reviews.</p>
<p>Abbey Rennemeyer has been a wonderful editor. After she has reviewed my posts for freeCodeCamp for over three years, it was clear that I would like to ask her to be the editor of this book as well. She helped me improve the book in many ways, and I am grateful for her help.</p>
<p>Quincy Larson founded the amazing community at freeCodeCamp, motivated me throughout emails and face to face discussions. I thank him for starting this incredible community, and for his friendship.</p>
<p>Estefania Cassingena Navone designed the cover of this book. I am grateful for her professional work and her patience with my perfectionism and requests.</p>
<p>Daphne Gray-Grant's website, <a target="_blank" href="https://www.publicationcoach.com/">"Publication Coach"</a>, has provided me with inspiring as well as technical advice that has greatly helped me with my writing process.</p>
<h3 id="heading-if-you-wish-to-support-this-book">If You Wish to Support This Book</h3>
<p>If you would like to support this book, you are welcome to buy the <a target="_blank" href="https://www.amazon.com/dp/B0CQXTJ5V5">Paperback version</a>, an <a target="_blank" href="https://www.buymeacoffee.com/omerr/e/197232">E-Book version</a>, or <a target="_blank" href="https://www.buymeacoffee.com/omerr">buy me a coffee</a>. Thank you!</p>
<h3 id="heading-contact-me">Contact Me</h3>
<p>This book has been created to help you and people like you learn, understand Git, and apply their knowledge in real life. </p>
<p>Right from the beginning, I asked for feedback and was lucky to receive it from great people (mentioned in the <a class="post-section-overview" href="#heading-acknowledgements">Acknowledgements</a>) to make sure the book achieves these goals. If you liked something about this book, felt that something was missing or needed improvement - I would love to hear from you. Please reach out at <a target="_blank" href="mailto:gitting.things@gmail.com">gitting.things@gmail.com</a>.</p>
<p>Thank you for learning and allowing me to be a part of your journey.</p>
<ul>
<li>Omer Rosenbaum</li>
</ul>
<h1 id="heading-appendixes">Appendixes</h1>
<h2 id="heading-additional-references-by-part">Additional References - By Part</h2>
<p>(Note - this is a short list. You can find a longer list of references on the <a target="_blank" href="https://www.buymeacoffee.com/omerr/e/197232">E-Book</a> or <a target="_blank" href="https://www.amazon.com/dp/B0CQXTJ5V5">printed</a> version.)</p>
<h3 id="heading-part-1">Part 1</h3>
<ul>
<li>Git Internals YouTube playlist - by Brief:<br><a target="_blank" href="https://www.youtube.com/playlist?list=PL9lx0DXCC4BNUby5H58y6s2TQVLadV8v7">https://www.youtube.com/playlist?list=PL9lx0DXCC4BNUby5H58y6s2TQVLadV8v7</a></li>
<li>Tim Berglund's lecture  - "Git From the Bits Up":<br><a target="_blank" href="https://www.youtube.com/watch?v=MYP56QJpDr4">https://www.youtube.com/watch?v=MYP56QJpDr4</a></li>
<li>as promised, docs: Git for the confused:<br><a target="_blank" href="https://www.gelato.unsw.edu.au/archives/git/0512/13748.html">https://www.gelato.unsw.edu.au/archives/git/0512/13748.html</a></li>
</ul>
<h3 id="heading-part-2">Part 2</h3>
<h4 id="heading-diffs-and-patches">Diffs and Patches</h4>
<p>Git Diffs algorithms:</p>
<ul>
<li><a target="_blank" href="https://en.wikipedia.org/wiki/Diff">https://en.wikipedia.org/wiki/Diff</a></li>
</ul>
<p>The most default diff algorithm in Git is Myers:</p>
<ul>
<li><a target="_blank" href="https://www.nathaniel.ai/myers-diff/">https://www.nathaniel.ai/myers-diff/</a></li>
<li><a target="_blank" href="https://blog.jcoglan.com/2017/02/12/the-myers-diff-algorithm-part-1/">https://blog.jcoglan.com/2017/02/12/the-myers-diff-algorithm-part-1/</a></li>
<li><a target="_blank" href="https://blog.robertelder.org/diff-algorithm/">https://blog.robertelder.org/diff-algorithm/</a></li>
</ul>
<h4 id="heading-git-merge">Git Merge</h4>
<ul>
<li><a target="_blank" href="https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging">https://git-scm.com/book/en/v2/Git-Tools-Advanced-Merging</a></li>
<li><a target="_blank" href="https://blog.plasticscm.com/2010/11/live-to-merge-merge-to-live.html">https://blog.plasticscm.com/2010/11/live-to-merge-merge-to-live.html</a></li>
</ul>
<h4 id="heading-git-rebase">Git Rebase</h4>
<ul>
<li><a target="_blank" href="https://jwiegley.github.io/git-from-the-bottom-up/1-Repository/7-branching-and-the-power-of-rebase.html">https://jwiegley.github.io/git-from-the-bottom-up/1-Repository/7-branching-and-the-power-of-rebase.html</a></li>
<li><a target="_blank" href="https://git-scm.com/book/en/v2/Git-Branching-Rebasing">https://git-scm.com/book/en/v2/Git-Branching-Rebasing</a></li>
</ul>
<h4 id="heading-beatles-related-resources-1">Beatles-Related Resources</h4>
<ul>
<li><a target="_blank" href="https://www.the-paulmccartney-project.com/song/ive-got-a-feeling/">https://www.the-paulmccartney-project.com/song/ive-got-a-feeling/</a></li>
<li><a target="_blank" href="https://www.cheatsheet.com/entertainment/did-john-lennon-or-paul-mccartney-write-the-classic-a-day-in-the-life.html/">https://www.cheatsheet.com/entertainment/did-john-lennon-or-paul-mccartney-write-the-classic-a-day-in-the-life.html/</a></li>
<li><a target="_blank" href="http://lifeofthebeatles.blogspot.com/2009/06/ive-got-feeling-lyrics.html">http://lifeofthebeatles.blogspot.com/2009/06/ive-got-feeling-lyrics.html</a></li>
</ul>
<h3 id="heading-part-3">Part 3</h3>
<ul>
<li><a target="_blank" href="https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified">https://git-scm.com/book/en/v2/Git-Tools-Reset-Demystified</a></li>
<li><a target="_blank" href="https://www.edureka.co/blog/common-git-mistakes/">https://www.edureka.co/blog/common-git-mistakes/</a></li>
</ul>
<h1 id="heading-about-the-author">About the Author</h1>
<p><a target="_blank" href="https://www.linkedin.com/in/omer-rosenbaum-034a08b9/">Omer Rosenbaum</a> is <a target="_blank" href="https://swimm.io/">Swimm</a>’s Chief Technology Officer. He's the author of the <a target="_blank" href="https://youtube.com/@BriefVid">Brief YouTube Channel</a>. He's also a cyber training expert and founder of Checkpoint Security Academy. He's the author of <a target="_blank" href="https://data.cyber.org.il/networks/networks.pdf">Computer Networks (in Hebrew)</a>. You can find him on <a target="_blank" href="https://twitter.com/Omer_Ros">Twitter</a>.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ How to Innovate as a Developer – a Roadmap to a Successful Tech Career [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ Welcome to this book that teaches you how to innovate as a developer. It isn’t just another step-by-step manual on creating specific products. It’s much more.  I’ve crafted this guide with a focus on equipping you with the mindset, skills, and habits... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/creators-guide-to-innovation-book/</link>
                <guid isPermaLink="false">66b99aedb0933e3341151c5c</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ creativity ]]>
                    </category>
                
                    <category>
                        <![CDATA[ innovation ]]>
                    </category>
                
                    <category>
                        <![CDATA[ self-improvement  ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Vahe Aslanyan ]]>
                </dc:creator>
                <pubDate>Fri, 22 Dec 2023 22:18:29 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/12/How-to-Innovate-as-Developer-Version-3-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Welcome to this book that teaches you how to innovate as a developer. It isn’t just another step-by-step manual on creating specific products. It’s much more. </p>
<p>I’ve crafted this guide with a focus on equipping you with the mindset, skills, and habits necessary for innovation at any scale – whether it's crafting a single line of code or developing an enterprise-level product.</p>
<p>In today's AI-dominated era, the bar for excellence is constantly rising. AI tools like ChatGPT are rapidly bridging the gap between average and advanced skills, changing the landscape of what it means to be a successful developer. </p>
<p>This guide is designed to help you not just keep pace but leap ahead, ensuring you’re operating at your peak.</p>
<p>Throughout my journey in product creation, I encountered countless books and courses. Often, they left me overwhelmed and without a complete picture. This guide is my solution to that problem – a comprehensive resource distilled from my experiences, designed to guide you in your tech career. </p>
<p>It’s not just about coding – it's about thinking, innovating, and solving problems in ways that matter.</p>
<p>In these pages, you’ll find practical advice and real-world examples to help you navigate the complexities of innovation and technology. Whether you're starting your journey or looking to elevate your skills, this guide will serve as your compass. It will open doors to networking opportunities with talented people, unlock previously closed avenues, and set you on a path to remarkable achievements.</p>
<p>By using the principles outlined in this guide, I've been able to launch top-tier data science bootcamps, cutting-edge products, and establish myself as a top voice in software development. Now, it’s your turn. This guide is more than a collection of insights – it's an action plan for success in an AI-driven world.</p>
<p>Are you ready to transform your approach, create groundbreaking solutions, and redefine what it means to be a successful tech innovator? The journey begins now. </p>
<p>By the end of this book, you will have embarked on a transformative journey that equips you with the tools and insights to realize your most ambitious creative visions. Here’s what you can expect to achieve:</p>
<ol>
<li><strong>Unleash Your Creative Genius</strong>: Unlock the full potential of your creativity, turning innovative ideas into groundbreaking projects that captivate and inspire.</li>
<li><strong>Master the Art of Adaptation</strong>: Gain the skills to fluidly navigate the ever-evolving landscape of technology and business, turning challenges into opportunities for growth and innovation.</li>
<li><strong>Transform Ideas into Impact</strong>: Learn how to convert abstract concepts into tangible, impactful products or services that resonate in the market.</li>
<li><strong>Develop a Future-Proof Mindset</strong>: Cultivate an adaptable, resilient mindset that prepares you not just for the present challenges but also for future advancements and shifts in your field.</li>
<li><strong>Build a Strong Personal Brand</strong>: Establish a compelling personal brand that showcases your unique talents and visions, making you a sought-after name in your industry.</li>
<li><strong>Harness the Power of Networking</strong>: Create a robust network of collaborators, mentors, and supporters that accelerates your path to success and opens doors to new opportunities.</li>
<li><strong>Achieve Professional Excellence</strong>: Attain a high level of proficiency and expertise in your chosen field, positioning yourself as a leading figure and an authority.</li>
<li><strong>Live Your Passion</strong>: Transform your passion into a rewarding career, ensuring that every day of your professional life is filled with purpose and enthusiasm.</li>
<li><strong>Foster Continuous Learning and Growth</strong>: Embrace a lifelong learning ethos, continually enhancing your skills and knowledge to stay ahead of the curve.</li>
<li><strong>Create a Legacy of Innovation</strong>: Leave a mark in your field with contributions that not only define current trends but also pave the way for future innovations.</li>
</ol>
<p>By the end of this guide, you’ll be more than just a creator – you'll be a visionary architect of the future, equipped with the knowledge, skills, and mindset to turn your dreams into reality and to make a lasting impact in the world of creation and innovation.</p>
<p>Also, I've turned this into an audiobook if you'd like to listen to it as well:</p>
<div class="embed-wrapper"><iframe style="border-radius:12px" src="https://open.spotify.com/embed/episode/3xV5UZ1l2HfDlzC6W7VbsU?utm_source=generator&amp;theme=0&amp;t=0" width="100%" height="152" title="Embedded content" loading="lazy"></iframe></div>

<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#1-creator-s-mindset-mastery-unlocking-the-power-of-innovative-thinking">Creator's Mindset Mastery: Unlocking the Power of Innovative Thinking</a></li>
<li><a class="post-section-overview" href="#2-success-systems-organizing-your-ideas-into-tangible-outcomes">Success Systems: Organizing Your Ideas into Tangible Outcomes</a></li>
<li><a class="post-section-overview" href="#3-resilience-in-creation-building-unshakable-mental-strength">Resilience in Creation: Building Unshakable Mental Strength</a></li>
<li><a class="post-section-overview" href="#4-creative-problem-solving-finding-unique-solutions-for-real-world-impact">Creative Problem-Solving: Finding Unique Solutions for Real-World Impact</a></li>
<li><a class="post-section-overview" href="#heading-5-skill-evolution-refining-your-abilities-for-industry-leadership">Skill Evolution: Refining Your Abilities for Industry Leadership</a></li>
<li><a class="post-section-overview" href="#6-productive-habits-daily-routines-that-propel-you-forward">Productive Habits: Daily Routines That Propel You Forward</a></li>
<li><a class="post-section-overview" href="#7-strategic-approaches-navigating-multiple-routes-to-achieve-your-goals">Strategic Approaches: Navigating Multiple Routes to Achieve Your Goals</a></li>
<li><a class="post-section-overview" href="#8-creator-s-confidence-trusting-your-gut-to-make-game-changing-decisions">Creator’s Confidence: Trusting Your Gut to Make Game-Changing Decisions</a></li>
<li><a class="post-section-overview" href="#9-have-a-10-year-plan-crafting-plans-that-shape-the-future">Have a 10 Year Plan: Crafting Plans That Shape the Future</a></li>
<li><a class="post-section-overview" href="#10-play-the-game-on-your-terms-fastest-way-to-achieving-whatever-you-want">Success on Your Terms: Defining and Achieving Your Personal Best</a></li>
<li><a class="post-section-overview" href="#11-powerful-networking-building-connections-that-propel-your-vision">Powerful Networking: Building Connections That Propel Your Vision</a></li>
<li><a class="post-section-overview" href="#12-risk-mastery-harnessing-uncertainty-for-game-changing-success">Risk Mastery: Leveraging Uncertainty for Revolutionary Creations</a></li>
<li><a class="post-section-overview" href="#13-turning-failures-to-wins-learning-from-setbacks-for-greater-success">Turning Failures to Wins: Learning from Setbacks for Greater Success</a></li>
<li><a class="post-section-overview" href="#14-mastering-change-navigate-and-conquer-the-unpredictable">Mastering Change: Navigate and Conquer the Unpredictable</a></li>
<li><a class="post-section-overview" href="#15-health-hack-fuel-your-ambition-with-wellness">Health Hacks: Fuel Your Ambition with Wellness</a></li>
<li><a class="post-section-overview" href="#16-fueled-by-passion-finding-purpose-in-what-you-love">Fueled by Passion: Finding Purpose in What You Love</a></li>
<li><a class="post-section-overview" href="#17-laser-focus-harnessing-the-power-of-concentration">Laser Focus: Harnessing the Power of Concentration</a></li>
<li><a class="post-section-overview" href="#18-skill-building-elevating-your-talents">Skill Building: Elevating Your Talents</a></li>
<li><a class="post-section-overview" href="#heading-19-solid-confidence-making-a-strong-impression">Building Solid Confidence: Making a Strong Impression</a></li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/p/2e0dd20c-1791-423b-acc1-dd687a86c175/20-boosting-productivity-enhancing-your-efficiency">Boosting Productivity: Enhancing Your Efficiency</a></li>
<li><a class="post-section-overview" href="#21-fall-like-a-thunderbolt-mastering-efficient-decision-making">Fall Like a Thunderbolt: Mastering Efficient Decision-Making</a></li>
<li><a class="post-section-overview" href="#22-breaking-boundaries-making-your-mark">Breaking Boundaries: Making Your Mark</a></li>
<li><a class="post-section-overview" href="#conclusion-2">Conclusion</a></li>
</ol>
<h2 id="heading-1-creators-mindset-how-to-unlock-the-power-of-innovative-thinking">1. Creator's Mindset: How to Unlock the Power of Innovative Thinking</h2>
<p>‌‌Curiosity, without a doubt, has been the powerhouse of my professional journey. From establishing businesses to software engineering, and from public speaking to writing, it's curiosity that has propelled me forward. It's a universal driver, fueling innovation and pushing the boundaries of what we deem possible. </p>
<p>Back in, say, 1900, who would have imagined our current technological marvels? Rockets entering the atmosphere or instant global communication – these were once figments of the imagination, and now they're part of our daily reality.</p>
<p>So, what's the most crucial aspect of developing a mindset? It’s the courage to be curious, to challenge the status quo. This isn’t about motivational speeches – it's practical mindset advice.</p>
<h3 id="heading-how-to-develop-a-curious-mindset">How to Develop a Curious Mindset:</h3>
<ol>
<li><strong>Be Flexible in Your Thinking</strong>: Challenge conventional wisdom. Build your own understanding of the world, as reality varies for each person. A businessperson sees opportunity in oranges, while a consumer sees nourishment. Similarly, a software engineer perceives the layers of technology behind a software application, unlike a non-technical business owner. This flexibility extends to reading habits as well. Diversify your reading to encompass both fiction and non-fiction, as each broadens your perspective in unique ways.</li>
<li><strong>Embrace Challenges</strong>: True mastery comes from tackling difficult problems. It’s easy to solve simple issues, but complex challenges deepen your understanding and skill.</li>
<li><strong>Persist Despite Obstacles</strong>: A curious mindset is futile without persistence. Overcoming hurdles, not succumbing to them, is what distinguishes a resilient and competitive person.</li>
<li><strong>Develop a Multi-Faceted Personality</strong>: Don’t limit yourself to a single trait or skill. Combine multiple skills – coding, creating, marketing, writing, speaking – to become a multifaceted person. This doesn’t imply working in isolation. Rather, collaboration is key to thriving. The goal is to be versatile and well-rounded.</li>
<li><strong>Overcome Fear of Failure</strong>: Treat failure as a learning opportunity. Adopt a scientific approach: experiment, analyze outcomes, and iterate. Each failure brings you closer to success.</li>
<li><strong>Adopt a Growth Mindset</strong>: Believe in the malleability of your intelligence and abilities. This mindset fosters resilience and a love for learning. View challenges as opportunities and setbacks as lessons.</li>
<li><strong>Cultivate Continuous Learning</strong>: Maintain the curiosity of a child. Explore, ask questions, and seek understanding. Learning from diverse sources leads to unique insights and ideas.</li>
<li><strong>Encourage Openness</strong>: Seek and accept feedback. Be willing to experiment with different methods and approaches. Avoid confining yourself to fixed labels or identities.</li>
<li><strong>Normalize Failure and Risk-Taking</strong>: View failure as a part of the learning journey. Be open to taking calculated risks and stepping out of your comfort zone.</li>
<li><strong>Develop Empathy and Collaborative Skills</strong>: Strive to understand different perspectives. Collaboration fosters creativity and leads to more effective solutions.</li>
<li><strong>Nurture Self-Efficacy</strong>: Believe in your ability to learn and grow. Set achievable goals to build confidence and maintain momentum.</li>
<li><strong>Maintain a Beginner’s Mindset</strong>: Approach familiar situations with openness and eagerness. Challenge your assumptions and beliefs regularly.</li>
<li><strong>Balance Discipline with Playfulness</strong>: While discipline is vital, so is playfulness in thinking. Creative constraints can sometimes spur greater creativity.</li>
</ol>
<p>In essence, cultivating a curious mindset is about embracing flexibility, challenging yourself, being persistent, and continuously learning and adapting. It’s about viewing the world through multiple lenses and being open to new experiences and ideas. </p>
<p>This mindset isn’t just a theoretical concept – it’s a practical, daily practice that leads to real-world success and innovation. It requires a balance of courage, discipline, and a willingness to step outside your comfort zone. </p>
<p>Embrace curiosity, not as a trait but as a philosophy, and watch as it transforms your approach to life and work, driving you towards continuous growth and achievement.</p>
<h2 id="heading-2-success-systems-how-to-organize-your-ideas-into-tangible-outcomes">2. Success Systems: How to Organize Your Ideas into Tangible Outcomes</h2>
<p>Embarking on a journey of growth and creativity isn't just about sporadic bursts of inspiration or genius. It's about establishing and adhering to a system, a structured approach that propels you towards your goals. </p>
<p>The most successful people, whether students or professionals, understand this critical concept. They are not inherently more intelligent or gifted. Rather, they employ effective systems that edge them closer to success.</p>
<h3 id="heading-understanding-systems-in-growth">Understanding Systems in Growth:</h3>
<p>Systems are goal-oriented pathways which, at their core, are designed to achieve specific objectives. They’re not about guaranteeing success but about significantly increasing its likelihood.</p>
<p>Effective systems also take a holistic approach and encompass various aspects of life. This ensures a harmonious balance between physical health, mental well-being, academic or professional achievements, and personal growth.</p>
<h3 id="heading-systems-for-creators-and-professionals">Systems for Creators and Professionals:</h3>
<p>Creators and professionals require systems that support their unique goals and lifestyles. These systems might include:</p>
<ul>
<li><strong>Scheduled Creative Time</strong>: Block out specific hours daily for creativity. No excuses, no distractions.</li>
<li><strong>Health Routine</strong>: Daily exercise and mental health practices are non-negotiable. Keep your body and mind in top condition.</li>
<li><strong>Journaling</strong>: Reflect and write daily. Track your progress and goals rigorously.</li>
<li><strong>Evening Planning</strong>: End your day by planning the next. Set clear tasks for tomorrow.</li>
<li><strong>Ongoing Education</strong>: Constantly learn. Dedicate time each week to skill development.</li>
<li><strong>Network Building</strong>: Regularly connect with industry peers. Make it a routine part of your week.</li>
<li><strong>Time Management</strong>: Use tools effectively. Organize your day, stick to your schedule.</li>
<li><strong>Seek Feedback</strong>: Regularly get and act on feedback. Don’t take it personally – just use it to improve.</li>
<li><strong>Strategic Planning</strong>: Set long-term goals and review them quarterly. Adjust as needed.</li>
<li><strong>Rest Periods</strong>: Schedule downtime. Rest is as important as work for long-term success.</li>
<li><strong>Financial Discipline</strong>: Manage your finances strictly. Budget, track, and plan.</li>
<li><strong>Digital Breaks</strong>: Implement digital detox periods weekly. Unplug to recharge.</li>
</ul>
<h3 id="heading-the-essence-of-systems-in-business">The Essence of Systems in Business:</h3>
<p>Peter M. Senge, in "The Fifth Discipline: The Art &amp; Practice of The Learning Organization," highlights the importance of systems thinking as a discipline for seeing wholes, patterns, and interrelationships. </p>
<p>This approach is vital in business. When you implement systems in your business, for instance, in content creation, you don’t just grow linearly by adding one platform after another. Instead, you expand exponentially. Each new system fuels and amplifies the previous ones, creating a synergy that accelerates growth. This is key, make use of it.</p>
<h3 id="heading-systems-discipline-and-freedom">Systems, Discipline, and Freedom:</h3>
<p>Systems and discipline are intrinsically linked. Approaching your work with a structured, consistent, and efficient system is like having a clear aim. Without it, you might come close to your target but not quite hit it. But with a well-defined system, you dramatically increase your chances of success. It’s about transforming random shots into targeted, precise hits.</p>
<h3 id="heading-building-and-mastering-systems">Building and Mastering Systems:</h3>
<p>Building effective systems is an art form and requires practice. The key is to start with one system, monitor its efficacy, and then gradually introduce others that complement and enhance the existing ones. Over time, you'll refine your skills in system creation and management. </p>
<h3 id="heading-example-of-a-system">Example of a System</h3>
<p>Whether you're a student, creator, or professional, the key to success lies in effectively designed systems. Let's take students as an example. Their goals often include excelling academically, earning a degree, and securing a job for financial stability. Achieving these isn't just about hard work –it's about creating and following systematic processes.</p>
<p>A student's system might include daily to-do lists, set the night before, outlining the next day's tasks. This methodical approach extends beyond academics. Regular physical activities, like gym sessions or walks, are also part of this system, integral to maintaining both mental sharpness and physical health.</p>
<p>The real power of these systems is in their feedback loops. It's a cycle of setting a goal, building a system around it, and constantly refining it based on feedback. This process ensures continuous improvement and is applicable across various fields. </p>
<p>For creators and professionals, similar systems can elevate their work and life balance, driving them towards their goals. </p>
<p>In essence, well-crafted systems are the backbone of success. They transform aspirations into tangible outcomes and are essential for anyone aiming to excel in their field, especially in an era where efficiency and effectiveness are key.</p>
<p>The beauty of this process lies in its iterative nature. Each system you build provides insights and knowledge, making you a more proficient systems creator.</p>
<p>Crafting a creative mindset and fostering original thinking is not just about unstructured creativity or random flashes of genius. It’s about building and adhering to a system that aligns with your goals. </p>
<p>This approach ensures that every step you take is calculated, every effort is maximized, and you remain steadfastly on the path to achieving your objectives. </p>
<p>Systems are not just tools for efficiency – they are the bedrock of sustained growth, creativity, and success. Build new systems upon your older systems, and you will see how your life changes.</p>
<h2 id="heading-3-resilience-in-creation-how-to-build-unshakable-mental-strength">3. Resilience in Creation: How to Build Unshakable Mental Strength</h2>
<p>‌‌To excel as a creator, your mental strength is as crucial as your talent. You need mental resilience to handle the challenges and rejections that come with creative work. This resilience is what keeps you going when the market is tough or your motivation wanes. </p>
<p>Remember, it's not about what you want – it's about what you work and ask for. So, let's dive into the core of mental strength for creatives.</p>
<h3 id="heading-the-importance-of-mental-resilience">The Importance of Mental Resilience</h3>
<p>Studies have shown that mental training can enhance muscle strength, indicating the significant impact of the mind on physical performance. So as you rise higher in your field, the need for a resilient mind increases proportionally.</p>
<h4 id="heading-pillars-of-mental-power-for-creatives">Pillars of Mental Power for Creatives</h4>
<ol>
<li><strong>Willpower and Self-Control</strong>: These are your shields against short-term temptations, keeping you on track towards long-term goals.</li>
<li><strong>Critical Thinking and Problem-Solving</strong>: Essential in making informed decisions and navigating complex situations.</li>
<li><strong>Emotional Intelligence</strong>: Key for managing personal and professional relationships.</li>
<li><strong>Memory and Learning</strong>: Fundamental for skill accumulation and personal development.</li>
<li><strong>Creativity and Innovation</strong>: Necessary for adapting to new situations and solving unconventional problems.</li>
<li><strong>Resilience and Mental Toughness</strong>: Helps you cope with challenges and grow from adversity.</li>
<li><strong>Adaptability and Flexibility</strong>: Crucial in today's ever-changing world.</li>
<li><strong>Motivation and Goal Setting</strong>: Drives your personal and professional growth.</li>
<li><strong>Decision-Making</strong>: Impacts every aspect of your life.</li>
<li><strong>Concentration and Focus</strong>: Enhances productivity and success in tasks.</li>
<li><strong>Communication Skills</strong>: Vital for building relationships and effective collaboration.</li>
<li><strong>Mindfulness and Self-Care</strong>: Important for mental health and overall well-being.</li>
<li><strong>Perspective and Gratitude</strong>: Enhances life satisfaction and happiness.</li>
</ol>
<h4 id="heading-cutting-out-bad-habits">Cutting Out Bad Habits</h4>
<p>Newton's First Law of Motion applies here: to change your state from inertia to action, you must consciously switch your behavior. Identify and actively work on eliminating detrimental habits like procrastination, lack of sleep, poor diet, excessive screen time, and negative self-talk. These habits hinder your mental and creative prowess.</p>
<h4 id="heading-less-obvious-habits-to-avoid">Less Obvious Habits to Avoid</h4>
<ul>
<li><strong>Multitasking</strong>: It scatters your focus and reduces efficiency.</li>
<li><strong>Isolation</strong>: Can lead to mental health issues.</li>
<li><strong>Overworking</strong>: Leads to burnout and reduced creativity.</li>
<li><strong>Substance Abuse</strong>: Impairs cognitive and emotional health.</li>
<li><strong>Mindless Entertainment</strong>: Detracts from productive activities.</li>
<li><strong>Negative News Consumption</strong>: Increases stress and anxiety.</li>
<li><strong>Rumination</strong>: Fuels anxiety and depression.</li>
<li><strong>Avoidance of Physical Activity</strong>: Negatively impacts mental clarity.</li>
<li><strong>Ignoring Mental Health</strong>: Can worsen mental health conditions.</li>
</ul>
<h4 id="heading-practices-for-enhancing-mental-power">Practices for Enhancing Mental Power</h4>
<p>Mental mastery as a creator is not just about having brilliant ideas. It's also about developing the mental resilience, discipline, and habits that support the consistent realization of those ideas. It's about building a mental framework that sustains your journey through ups and downs.</p>
<p>Here are some activities that can help develop this mental resilience and make your brain stronger:</p>
<h4 id="heading-journaling">Journaling</h4>
<p><strong>What It Is:</strong> Journaling is the practice of regularly writing down thoughts, experiences, and reflections. It's a powerful tool for self-awareness and stress reduction.</p>
<p><strong>How to Implement:</strong></p>
<ul>
<li><strong>Daily Reflection:</strong> Dedicate a few minutes each day to jot down your thoughts, feelings, and experiences. This can include reflections on your day, ideas, worries, and aspirations.</li>
<li><strong>Structured Format:</strong> Consider using prompts or specific sections (like goals, gratitude, challenges) to structure your entries. This can make journaling more focused and meaningful.</li>
<li><strong>Consistency:</strong> Make it a daily habit, perhaps at the start or end of your day. Consistency is key to making journaling a powerful tool for self-improvement.</li>
</ul>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Clarifies thoughts and feelings:</strong> Helps process complex emotions and untangle thoughts.</li>
<li><strong>Tracks personal growth over time:</strong> Allows you to see how you've evolved and grown.</li>
<li><strong>Serves as a problem-solving tool:</strong> Journaling about challenges can lead to new perspectives and solutions.</li>
</ul>
<h4 id="heading-setting-smart-goals">Setting SMART Goals</h4>
<p><strong>What It Is:</strong> SMART goals are objectives that are Specific, Measurable, Achievable, Relevant, and Time-bound.</p>
<p><strong>How to Implement:</strong></p>
<ul>
<li><strong>Specific:</strong> Define clear, detailed goals. For example, "Increase coding proficiency in Python by completing a specific coding course in three months" instead of "Get better at coding."</li>
<li><strong>Measurable:</strong> Set benchmarks to measure progress, like completing modules or projects.</li>
<li><strong>Achievable:</strong> Ensure goals are realistic and attainable within your resources and time constraints.</li>
<li><strong>Relevant:</strong> Align goals with your broader ambitions and values.</li>
<li><strong>Time-bound:</strong> Set deadlines for your goals to create a sense of urgency and motivation.</li>
</ul>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Provides clear direction and focus:</strong> Makes it easier to plan and allocate resources.</li>
<li><strong>Enhances motivation:</strong> Clear goals give a sense of purpose and drive.</li>
<li><strong>Facilitates better planning and time management:</strong> Helps prioritize tasks and manage your time effectively.</li>
</ul>
<h4 id="heading-deep-work">Deep Work</h4>
<p><strong>What It Is:</strong> Coined by Cal Newport, it refers to the practice of working in a state of high concentration without distractions on cognitively demanding tasks.</p>
<p><strong>How to Implement:</strong></p>
<ul>
<li><strong>Scheduled Blocks:</strong> Allocate specific time blocks for deep work in your daily schedule. This could be during your most productive hours.</li>
<li><strong>Minimize Distractions:</strong> Create a distraction-free environment. Turn off notifications and limit interruptions. Inform others of your focused work time.</li>
<li><strong>Regular Breaks:</strong> Include short breaks to maintain high levels of focus and prevent burnout.</li>
</ul>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Increases productivity and efficiency:</strong> Allows you to get more done in less time.</li>
<li><strong>Enhances the quality of work:</strong> Focused attention leads to higher-quality results.</li>
<li><strong>Encourages creativity and problem-solving:</strong> Deep work states often lead to innovative ideas and solutions.</li>
</ul>
<h4 id="heading-progress-tracking">Progress Tracking</h4>
<p><strong>What It Is:</strong> The practice of regularly monitoring and assessing your progress towards goals.</p>
<p><strong>How to Implement:</strong></p>
<ul>
<li><strong>Regular Check-ins:</strong> Schedule weekly or monthly reviews of your goals and progress. Reflect on what you've accomplished and what needs more attention.</li>
<li><strong>Use Tools:</strong> Utilize apps or planners for tracking. Tools like Trello, Asana, or even a simple spreadsheet can be effective.</li>
<li><strong>Adjust Goals:</strong> Be flexible to adjust your strategies based on your progress. If a goal seems unattainable, modify it to be more realistic.</li>
</ul>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Keeps you accountable and motivated:</strong> Regular check-ins keep your goals at the forefront of your mind.</li>
<li><strong>Provides insight into what's working and what's not:</strong> Helps you tweak your strategies for better results.</li>
<li><strong>Helps in recognizing and celebrating achievements:</strong> Acknowledging progress can be a significant morale booster.</li>
</ul>
<h4 id="heading-combating-negative-self-talk">Combating Negative Self-Talk</h4>
<p><strong>What It Is:</strong> Transforming self-critical or negative thoughts into positive affirmations.</p>
<p><strong>How to Implement:</strong></p>
<ul>
<li><strong>Awareness:</strong> Notice when you have negative thoughts. Be mindful of your internal dialogue.</li>
<li><strong>Challenge and Replace:</strong> Actively challenge these thoughts and replace them with positive affirmations. For example, replace "I can't do this" with "I am learning and improving every day."</li>
<li><strong>Positive Reinforcement:</strong> Regularly remind yourself of your strengths and achievements. Keep a record of compliments and successes.</li>
</ul>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Improves self-esteem and confidence:</strong> Builds a more positive self-image.</li>
<li><strong>Reduces stress and anxiety:</strong> Positive thinking leads to a calmer mind.</li>
<li><strong>Encourages a positive mindset:</strong> Fosters a more optimistic outlook on life and challenges.</li>
</ul>
<h4 id="heading-gratitude-journaling">Gratitude Journaling</h4>
<p><strong>What It Is:</strong> Writing down things you are grateful for on a regular basis.</p>
<p><strong>How to Implement:</strong></p>
<ul>
<li><strong>Daily Practice:</strong> Set aside time each day to list at least three things you're grateful for. These could range from small joys to major achievements.</li>
<li><strong>Be Specific:</strong> The more specific your entries, the more impactful. Instead of "I'm grateful for my family," try "I'm grateful for my sister's support during a tough time today."</li>
</ul>
<p><strong>Benefits:</strong></p>
<ul>
<li><strong>Enhances mental well-being:</strong> Consistently focusing on the positive aspects of life improves overall happiness.</li>
<li><strong>Cultivates a positive outlook:</strong> Helps in seeing the good even in challenging situations.</li>
<li><strong>Improves sleep and reduces stress:</strong> Gratitude has been linked to better sleep quality and reduced feelings of anxiety and depression.</li>
</ul>
<p>Remember, your greatest asset as a creative is not just your talent, but the mental power you harness to bring your talent to fruition.</p>
<h2 id="heading-4-creative-problem-solving-how-to-find-unique-solutions-for-real-world-impact">4. Creative Problem-Solving: How to Find Unique Solutions for Real-World Impact</h2>
<p>‌‌Creative problem-solving is a vital skill that empowers you to find unique solutions with real-world impact. By leveraging various techniques, you can unleash your imagination, challenge assumptions, and explore new perspectives to address complex challenges. </p>
<p>In this chapter, we will explore several powerful creative problem-solving techniques that you can apply to drive innovation and navigate uncertainty in a rapidly changing world.</p>
<h3 id="heading-balance-divergent-and-convergent-thinking">Balance Divergent and Convergent Thinking</h3>
<p>Creative problem-solving involves the interplay of divergent and convergent thinking. </p>
<p>Divergent thinking is the process of generating a diverse array of ideas in response to a problem. Convergent thinking then involves evaluating and narrowing down these ideas to identify the most promising solutions. </p>
<p>Balancing these two modes of thinking is essential for effective problem-solving.</p>
<h4 id="heading-examples-of-divergent-and-convergent-thinking">Examples of divergent and convergent thinking</h4>
<p><strong>Divergent thinking</strong>: Generate a diverse array of ideas in response to a problem.</p>
<ul>
<li>Write down at least 10 different solutions to the problem.</li>
<li>Avoid judging any ideas during this stage.</li>
</ul>
<p><strong>Convergent thinking</strong>: Evaluate and narrow down the ideas to identify the most promising solutions.</p>
<ul>
<li>Group the ideas into categories based on their theme or focus.</li>
<li>Select the best 3-5 solutions that best address the problem.</li>
</ul>
<p>Every problem has a solution. It comes down to what you have and how well you use it. But be careful – if you're not precise, you could end up spending more and using up what you have faster. It's much better to focus on solving the problem than to worry about mistakes you've made.</p>
<p>Always remember, for every problem, there's an answer out there. It depends on how determined you are and how cleverly you use what you have. If you really want it, you'll find a way. You're in charge.</p>
<p>This way of thinking means you're ahead of the game, not just reacting to things. You're in control, figuring out what you have at your disposal, and using it wisely. The main thing is to be efficient and think smart. Keep your eye on the goal and stay motivated. With this attitude, you can handle any challenge that comes your way.</p>
<h3 id="heading-reframe-problems-as-questions">Reframe Problems as Questions</h3>
<p>One powerful technique for creative problem-solving is to reframe problems as questions. By asking open-ended questions that challenge assumptions, people can approach problems from different angles and stimulate creative thinking. This technique encourages the exploration of unconventional ideas and fosters a culture of innovation.</p>
<h4 id="heading-example-of-reframing-a-problem-as-a-question">Example of reframing a problem as a question</h4>
<p><strong>Ask open-ended questions</strong>: Frame the problem as a question that encourages creative thinking.</p>
<ul>
<li>"How can we improve the current solution?"</li>
<li>"What are the underlying causes of this issue?"</li>
</ul>
<p><strong>Encourage brainstorming</strong>: Create a supportive environment for idea generation.</p>
<ul>
<li>Set aside a dedicated time for brainstorming sessions.</li>
<li>Encourage team members to share their ideas without fear of judgment.</li>
</ul>
<p>Just like blending divergent and convergent thinking, my approach to tackling issues starts with pinpointing the problem, then seeking the solution. </p>
<p>How? It's all about posing the right questions. You see, life's effectiveness boils down to this skill. Pose the wrong questions, and you're on a fast track to squandering your resources, be it time, energy, money, or anything else valuable. But, when you ask the right questions, the rewards are substantial.</p>
<p>Take ChatGPT as an example. Feed it a <a target="_blank" href="https://www.freecodecamp.org/news/learn-prompt-engineering-full-course/">precise and well-structured prompt</a>, and it churns out wonders. But if you pose the wrong questions, the output can be less insightful and sometimes even wrong. </p>
<h3 id="heading-example-analyzing-the-root-problem-in-education">Example: Analyzing the Root Problem in Education</h3>
<p><strong>Current State of Education:</strong></p>
<ul>
<li><strong>Path Followed:</strong> Traditional education involves years of lectures and classroom learning.</li>
<li><strong>Self-Learning:</strong> Despite structured classes, much of the actual learning occurs independently.</li>
<li><strong>Financial Investment:</strong> The cost of formal education can be substantial, often reaching hundreds of thousands of dollars.</li>
<li><strong>Questioning Efficiency:</strong> Is the traditional educational path the most efficient for achieving career goals?</li>
</ul>
<p><strong>Identifying the Core Issue:</strong></p>
<ul>
<li>The main problem seems to be the efficiency of the education system in terms of time, cost, and methodology.</li>
<li>Does the current system optimally equip students for their career aspirations?</li>
</ul>
<p><strong>Exploring Alternatives and Solutions:</strong></p>
<ul>
<li><strong>Need for Innovation:</strong> There's a gap in efficient education pathways that effectively align with career goals.</li>
<li><strong>Potential Solutions:</strong> Alternative learning models, technology integration, personalized education plans, competency-based learning.</li>
<li><strong>Assessment of Current Alternatives:</strong> Existing alternatives may not fully address the core issues of efficiency and effectiveness.</li>
</ul>
<p><strong>Innovation Opportunities:</strong></p>
<ul>
<li><strong>Customization:</strong> Tailored learning experiences that align with personal career paths.</li>
<li><strong>Technology Integration:</strong> Using AI and online platforms for more personalized and adaptable learning experiences.</li>
<li><strong>Cost and Time Efficiency:</strong> Programs that offer faster, more focused learning paths at a lower cost.</li>
<li><strong>Real-World Application:</strong> Emphasizing practical skills and real-world experience over theoretical knowledge.</li>
</ul>
<p>By thoroughly examining the fundamental aspects of the problem and exploring potential solutions, you’re setting the stage for innovative approaches in education. This process goes beyond merely identifying issues; it's about reconstructing the education paradigm to better fit modern needs and efficiency standards.</p>
<h3 id="heading-dont-immediately-judge-ideas">Don't Immediately Judge Ideas</h3>
<p>Refining and evaluating ideas post-generation is a critical phase in the brainstorming process, requiring both creative freedom and analytical rigor. </p>
<p>The initial stage of brainstorming is characterized by an open, judgment-free environment to encourage a wide range of ideas, from the conventional to the wildly imaginative. This phase is crucial for tapping into the team's collective creativity and avoiding premature dismissal of potential solutions.</p>
<h4 id="heading-how-to-foster-an-open-idea-environment">How to Foster an Open Idea Environment:</h4>
<ol>
<li><strong>Capture All Ideas:</strong> During brainstorming, it’s crucial to document every idea, no matter how unconventional. Tools like Trello boards for project management, Google Docs for real-time collaboration, or even simple sticky notes on a whiteboard can be effective.<br>For example, in a brainstorming session focused on improving user interface design, ideas can range from standard layout changes to more radical, gamified interactions. Every suggestion is documented without immediate critique.</li>
<li><strong>Non-Evaluative Phase:</strong> At this stage, the primary objective is to gather diverse perspectives without analysis or criticism. This approach ensures inclusivity and encourages participants to share freely.<br>In a team brainstorming session for a new marketing campaign, for example, all ideas are welcomed, from traditional print media strategies to innovative social media challenges, without immediate scrutiny or debate.</li>
<li><strong>Later Evaluation:</strong> After the brainstorming session, the team reconvenes to assess the gathered ideas. Criteria for evaluation might include feasibility, cost, potential impact, alignment with company goals, or innovation level. Using a weighted scoring system or a decision matrix can help objectively evaluate and prioritize the ideas.</li>
</ol>
<p><strong>Personal Experience with Visual Tools:</strong> My experience with whiteboards has been transformative in visualizing and connecting ideas. </p>
<p>For instance, while working on a software development project, mapping out user flow and interface elements on a whiteboard helped identify usability issues and innovative features that wouldn't have been apparent in a traditional discussion format.</p>
<h4 id="heading-how-to-apply-the-process-in-team-settings">How to Apply the Process in Team Settings:</h4>
<ol>
<li><strong>Collaborative Visualization:</strong> Taking inspiration from team-based problem-solving approaches like those in 'House MD,' a collaborative visualization process can be applied in settings like product development meetings. Here, each team member contributes ideas for new product features, which are then visually mapped out to see how they fit into the overall product design.</li>
<li><strong>Structured Analysis:</strong> In this phase, the team categorizes the ideas. For instance, in a session focused on enhancing customer service, ideas might be grouped into technology upgrades, staff training, or policy changes. The team then analyzes these categories to decide which ideas are most viable and impactful, leading to a clearer path forward.</li>
</ol>
<p>By combining the freedom of creative brainstorming with structured analysis, teams can ensure that they not only generate a wide range of ideas but also effectively refine and select the best ones. This approach leads to more innovative solutions and successful project outcomes.</p>
<p>Whiteboards were a game-changer for me, especially during my high school years. Maybe saying they were the sole reason I got my diploma is stretching it a bit, but they certainly played a huge part. </p>
<p>Whenever I face a new challenge or want to learn something new, I turn to my whiteboard. It’s amazing how the simple act of writing things down sparks a flow of ideas. And I'm not alone in this. Many software engineers, CEOs, and colleagues I know swear by it.</p>
<p>But it's not just about whiteboards. It’s about the way they facilitate problem-solving, especially in a team setting. Ever watched House MD? The way they brainstorm and discuss cases is a perfect example. </p>
<p>The key is to lay out the problem, get everyone involved in the discussion, and then map out the ideas, sorting them from best to worst. Once you have this list, start tackling the problem. This approach often leads you right to the solution.</p>
<h3 id="heading-use-what-if-scenarios">Use "What If" Scenarios</h3>
<p>"What if" scenarios are a powerful tool for exploring potential solutions and generating new ideas. By asking hypothetical questions that challenge assumptions, you can break free from conventional thinking and consider innovative approaches to problem-solving. </p>
<p>This technique encourages you to stretch your imagination and think beyond the boundaries of existing solutions.</p>
<h4 id="heading-example-of-a-what-if-scenario">Example of a "what-if" scenario</h4>
<p><strong>Ask Hypothetical Questions</strong>: Explore potential solutions by asking "what if", and then exploring that possibility.</p>
<ul>
<li>"What if we implemented this new technology?"</li>
<li>"What if we changed our strategy to address the issue?"</li>
</ul>
<p><strong>Explore Different Perspectives</strong>: Consider the implications of each scenario from various viewpoints.</p>
<ul>
<li>How would each scenario impact the problem?</li>
<li>What are the potential benefits and drawbacks of each scenario?</li>
</ul>
<p>When facing a complex challenge, there's a strategy I always lean on. It starts with a question. What's this challenge really about? </p>
<p>To tackle it effectively, I write it down. Visualizing the problem on paper (or on a whiteboard) instantly makes it more manageable. </p>
<p>Then, I go a step further – I create a pros and cons list. This simple exercise of listing the advantages and disadvantages brings clarity and perspective to the issue at hand.</p>
<p>This approach helps you get organized, but it also helps you break down the challenge into smaller, more understandable parts. By doing this, you shift from feeling overwhelmed to being in control. It's a method that transforms a seemingly insurmountable problem into a series of manageable tasks.</p>
<p>So next time you're up against a tough situation, remember this technique. Write it down, envision it, and weigh the pros and cons. It's a practical, straightforward way to navigate complex challenges and find effective solutions. This is about taking actionable steps, being methodical, and keeping your focus on finding a solution.</p>
<h3 id="heading-focus-on-quantity-over-quality-at-first">Focus on Quantity Over Quality at First</h3>
<p>During the ideation phase, it's important to focus on generating a large quantity of ideas without prematurely evaluating their quality. </p>
<p>This technique allows you to explore a wide range of possibilities, including unconventional and out-of-the-box ideas. Later, you can evaluate these ideas and refine them to identify the most promising solutions.</p>
<h4 id="heading-example-focusing-on-quantity-over-quality">Example focusing on quantity over quality</h4>
<p><strong>Generate a Large Number of Ideas</strong>: During the ideation phase, focus on quantity over quality.</p>
<ul>
<li>Write down at least 20 ideas in the first brainstorming session.</li>
<li>Avoid evaluating the ideas during this stage.</li>
</ul>
<p><strong>Evaluate and Refine Ideas Later</strong>: After the ideation phase, evaluate and refine the ideas to identify the most promising solutions.</p>
<ul>
<li>Use criteria relevant to the problem to rank the ideas.</li>
<li>Select the best 3-5 solutions to further explore.</li>
</ul>
<p>In the world of problem-solving, I usually advocate for quality over quantity. Ideally, focusing on one substantial project rather than scattering efforts across a hundred smaller ones makes more sense. But when it comes to tackling challenges where a quality-focused approach doesn't cut it, it's time to shift gears to quantity.</p>
<p>When you hit a wall with a problem, try bombarding it with ideas – lots of them. Think of 20, 30, or even 40 different ways to approach the issue. It's like throwing everything you've got at the problem to see what sticks. This method often leads to the breakthrough you need, like cracks beginning to show in an ice wall.</p>
<p>Of course, it's important to sift through these ideas later, refining and filtering them to find the most viable solutions. But initially, it’s all about volume. Attack the problem from every angle imaginable. This strategy can create the momentum needed to break through even the toughest challenges.</p>
<p>So next time you're stuck, remember: if quality approaches aren't working, switch to quantity. Flood the problem with ideas, and more often than not, you'll find your solution amidst the deluge and can then focus on quality again. </p>
<p>This method is about being relentless, versatile, and open to all possible solutions. Keep pushing, keep innovating, and watch as the seemingly unsolvable becomes solvable.</p>
<h3 id="heading-switch-roles">Switch Roles</h3>
<p>Switching roles can help you approach problems from different perspectives and generate new ideas. This technique involves imagining yourself in someone else's shoes and considering how they might approach the problem. </p>
<p>By adopting alternative viewpoints, you can challenge your own assumptions and uncover innovative solutions.</p>
<h4 id="heading-example-of-switching-roles">Example of switching roles</h4>
<p><strong>Imagine Different Perspectives</strong>: Adopt alternative viewpoints to approach the problem from different perspectives.</p>
<ul>
<li>Consider how each team member might approach the problem.</li>
<li>Reflect on how a customer or stakeholder might view the issue.</li>
</ul>
<p><strong>Challenge Assumptions</strong>: Question the assumptions underlying the problem.</p>
<ul>
<li>Identify the core assumptions and explore how they might be challenged or changed.</li>
<li>Consider alternative viewpoints that could lead to innovative solutions.</li>
</ul>
<p>If you've ever read "Think and Grow Rich," you might recall a fascinating section where the author discusses visualizing conversations with admired figures to solve problems. It's a technique that can be incredibly effective for creators and writers. </p>
<p>Imagine, for instance, you're tackling a challenge. How would someone like Iman Gadzhi approach it? Or what unique solution might Mr. Beast come up with? Even considering Robert Greene's perspective could offer a fresh angle.</p>
<p>I often find myself doing this almost instinctively, but consciously applying it can be a powerful tool for creative problem-solving. It's about stepping outside your usual thought patterns and asking, "How would these successful people handle this situation?" </p>
<p>This method doesn't just offer potential solutions – it also broadens your creative thinking and pushes you to consider approaches outside your comfort zone.</p>
<p>So next time you're faced with a challenge, pause and think: What would my role models or favorite creators do in this situation? </p>
<p>This approach is a practical strategy that can help you unlock creative, effective solutions. It's about drawing inspiration from the best, adapting their mindset, and applying it to your unique challenges. Give it a try, and you might be surprised at the innovative ideas you come up with.</p>
<h3 id="heading-use-synectics">Use Synectics</h3>
<p><a target="_blank" href="https://en.wikipedia.org/wiki/Synectics">Synectics</a> is a technique that helps you tap into the irrational, non-traditional part of your brain to think in more creative ways. </p>
<p>This approach involves selecting an analogy, force-fitting it to the problem, viewing the problem from different angles, and developing a list of possible solutions. By leveraging synectics, you can break free from conventional thought patterns and explore unconventional ideas.</p>
<h4 id="heading-example-of-how-to-use-synectics">Example of how to use synectics</h4>
<p><strong>Select an Analogy</strong>: Choose an analogy that is unrelated to the problem but shares some similarities.</p>
<ul>
<li>For example, if the problem is about improving communication, an analogy could be the nervous system.</li>
</ul>
<p><strong>Force-Fit the Analogy</strong>: Adapt the analogy to fit the problem.</p>
<ul>
<li>Identify the key components of the analogy and explore how they might be applied to the problem.</li>
</ul>
<p><strong>View the Problem from Different Angles</strong>: Consider the problem from various perspectives informed by the analogy.</p>
<ul>
<li>How would the nervous system approach the communication issue?</li>
<li>What insights can be gained from applying the analogy to the problem?</li>
</ul>
<p><strong>Develop Possible Solutions</strong>: Use the insights gained from the analogy to develop possible solutions.</p>
<ul>
<li>List 3-5 potential solutions that address the problem in a new way.</li>
</ul>
<p><strong>Determine Next Steps</strong>: Outline the next steps for implementing and evaluating the solutions.</p>
<ul>
<li>Include details on who will be responsible, when the work will be completed, where the work will take place, why the solution is being chosen, and how the solution will be evaluated.</li>
</ul>
<p>This method might seem unconventional, almost a last resort, but its effectiveness can be surprising. While often used for concept clarification, synectics is equally powerful for addressing new challenges. It pushes you beyond the usual thought patterns and opens up a world where creative solutions flourish.</p>
<p>In summary, these creative problem-solving techniques provide a systematic approach to unleash imagination, challenge assumptions, and explore new perspectives. </p>
<p>Creative problem-solving is a skill that you can develop and hone over time. By embracing a flexible and adaptable mindset, you can unlock your creative potential to address complex challenges.</p>
<h2 id="heading-5-skill-evolution-refining-your-abilities-for-industry-leadership">5. Skill Evolution: Refining Your Abilities for Industry Leadership</h2>
<p>To achieve market dominance, you need a blend of hard work, smart strategies, and relentless dedication. It’s about honing your skills to such an extent that you stand apart in your field. </p>
<p>Let’s break down the essentials for refining your abilities and establishing yourself as a market leader.</p>
<h3 id="heading-master-one-core-skill">Master One Core Skill</h3>
<p>Start by becoming exceptional in one key area. This is about depth, not breadth. </p>
<p>In a world with infinite possibilities, it’s tempting to try to do it all. Resist this urge. Focus your energy on becoming the best in a specific area.</p>
<p>Take Amazon, for instance. It began as a simple bookstore and mastered this niche before expanding. </p>
<p>To dominate the market, you need to reach a level where your skills are unparalleled in your chosen domain. This requires an unwavering commitment and a relentless pursuit of excellence.</p>
<p><strong>Step 1: Identify Your Skill</strong></p>
<ul>
<li>Assess your interests and strengths.</li>
<li>Research market demand for various skills.</li>
<li>Select one that aligns with both your interest and market demand.</li>
</ul>
<p><strong>Step 2: Deepen Your Knowledge</strong></p>
<ul>
<li>Enroll in specialized courses or workshops.</li>
<li>Study industry literature and follow thought leaders in your chosen field.</li>
</ul>
<p><strong>Step 3: Practical Application</strong></p>
<ul>
<li>Work on projects that allow you to apply and hone your skill.</li>
<li>Seek feedback and continuously refine your approach.</li>
</ul>
<p><strong>Step 4: Showcase Your Expertise</strong></p>
<ul>
<li>Create a portfolio or blog to demonstrate your skill and progress.</li>
<li>Share your work on professional networks like LinkedIn or industry-specific platforms.</li>
</ul>
<h3 id="heading-develop-an-excellent-work-ethic">Develop an Excellent Work Ethic</h3>
<p>Market dominance demands both hard and smart work. This is about putting in the hours and also being strategic in your approach. </p>
<p>It’s not enough to just work long hours – you need to work effectively. This involves constantly learning, adapting, and optimizing your strategies to stay ahead.</p>
<p><strong>Step 1: Set Clear Goals</strong></p>
<ul>
<li>Define what “excellence” means in your chosen field.</li>
<li>Set short-term and long-term goals that are specific, measurable, and realistic.</li>
</ul>
<p><strong>Step 2: Establish a Routine</strong></p>
<ul>
<li>Develop a daily schedule that balances work, learning, and rest.</li>
<li>Include specific times for focused work, skill development, and breaks.</li>
</ul>
<p><strong>Step 3: Continual Learning</strong></p>
<ul>
<li>Keep up-to-date with the latest developments in your field.</li>
<li>Regularly challenge yourself with new projects or learning opportunities.</li>
</ul>
<p><strong>Step 4: Measure and Adapt</strong></p>
<ul>
<li>Regularly review your progress towards your goals.</li>
<li>Be open to adapting your strategies based on what you learn.</li>
</ul>
<h3 id="heading-strong-branding-and-marketing">Strong Branding and Marketing</h3>
<p>Your voice in the market is crucial. Develop a <a target="_blank" href="https://www.freecodecamp.org/news/branding-for-developer-freelancers/">strong personal or business brand</a>. This is about how you present yourself, your values, and your unique selling proposition. </p>
<p>Branding isn’t just about visibility – it’s about being known for something specific and valuable.</p>
<p><strong>Step 1: Define Your Brand</strong></p>
<ul>
<li>Determine what unique value you can offer.</li>
<li>Define your brand’s voice, style, and core message.</li>
</ul>
<p><strong>Step 2: Build Your Online Presence</strong></p>
<ul>
<li>Create professional profiles on social media.</li>
<li>Engage with your audience through content like blog posts, videos, or podcasts.</li>
</ul>
<p><strong>Step 3: Network</strong></p>
<ul>
<li>Attend industry events and engage in online communities.</li>
<li>Build relationships with other professionals and potential clients.</li>
</ul>
<p><strong>Step 4: Consistency and Quality</strong></p>
<ul>
<li>Ensure all your content and interactions align with your brand identity.</li>
<li>Focus on delivering consistent, high-quality work.</li>
</ul>
<h3 id="heading-first-mover-advantage">First Mover Advantage</h3>
<p>Being first in a new market or technology can be a significant advantage. Early adopters and innovators often become the go-to experts in their fields. </p>
<p>Like <a target="_blank" href="https://www.youtube.com/results?search_query=ali+abdaal+study+guides">Ali Abdaal</a> with his unique study guides, being first allows you to set the standard and lead the way.</p>
<p><strong>Step 1: Market Research</strong></p>
<ul>
<li>Stay informed about emerging trends and technologies in your field.</li>
<li>Identify gaps in the market or upcoming opportunities.</li>
</ul>
<p><strong>Step 2: Rapid Development</strong></p>
<ul>
<li>Develop a prototype or concept quickly to test the market.</li>
<li>Be prepared to pivot or adapt based on feedback.</li>
</ul>
<p><strong>Step 3: Launch and Promote</strong></p>
<ul>
<li>Launch your product or service with a clear marketing strategy.</li>
<li>Utilize social media, industry contacts, and relevant platforms to promote your innovation.</li>
</ul>
<p><strong>Step 4: Continuous Improvement</strong></p>
<ul>
<li>Gather data and feedback post-launch.</li>
<li>Iterate and improve your offering based on user feedback.</li>
</ul>
<h3 id="heading-beyond-the-basics-what-more-can-you-do">Beyond the Basics: What More Can You Do?</h3>
<p>Once you’ve mastered these fundamentals, it’s time to scale. This doesn’t mean losing focus on your core area but rather expanding your influence and applying your expertise in new, related areas. It’s about leveraging your foundational strengths to explore new opportunities.</p>
<p><strong>Step 1: Master Your Core Area</strong></p>
<ul>
<li>Ensure you have a strong foundation and are recognized in your primary skill area.</li>
</ul>
<p><strong>Step 2: Explore Related Fields</strong></p>
<ul>
<li>Identify related skills or sectors where your expertise can be applied.</li>
<li>Start learning and experimenting in these areas.</li>
</ul>
<p><strong>Step 3: Diversify Your Portfolio</strong></p>
<ul>
<li>Take on projects that challenge you in new ways.</li>
<li>Collaborate with others in areas outside your core expertise.</li>
</ul>
<p><strong>Step 4: Build a Team or Network</strong></p>
<ul>
<li>If feasible, build a team that complements your skills.</li>
<li>Network with professionals in related fields for collaborative opportunities.</li>
</ul>
<h3 id="heading-persistence-and-resilience">Persistence and Resilience</h3>
<p>The journey to market dominance is filled with challenges. Your ability to persist, to stand firm against the odds, is what will define your success. This resilience is often what separates market leaders from the rest.</p>
<p><strong>Step 1: Develop a Growth Mindset</strong></p>
<ul>
<li>View challenges as opportunities for growth.</li>
<li>Embrace failure as a learning tool.</li>
</ul>
<p><strong>Step 2: Build a Support System</strong></p>
<ul>
<li>Establish a network of mentors, peers, and supporters.</li>
<li>Seek feedback and advice regularly.</li>
</ul>
<p><strong>Step 3: Stay Focused on Your Vision</strong></p>
<ul>
<li>Regularly remind yourself of your long-term goals and why they matter.</li>
<li>Avoid getting sidetracked by short-term setbacks.</li>
</ul>
<p><strong>Step 4: Self-Care</strong></p>
<ul>
<li>Implement routines for mental and physical wellness.</li>
<li>Recognize the importance of breaks and downtime for long-term success.</li>
</ul>
<h3 id="heading-scaling-your-expertise">Scaling Your Expertise</h3>
<p>With a solid foundation in place, consider branching out. This could mean exploring new markets, developing new products, or even educating others in your area of expertise. The key is to maintain the quality and depth of your core offering while exploring these new avenues.</p>
<p>Standing out is a result of a combination of factors – mastery of a core skill, a strong work ethic, strategic specialization, effective branding, seizing the first mover advantage, and the resilience to stand firm against challenges. It’s a journey that requires patience, persistence, and the ability to adapt and grow. </p>
<p>Once you’ve solidified your position, scaling becomes the next step to broadening your impact. </p>
<p>Remember, success in this realm isn’t about being the smartest or the hardest working – it's about being the most committed and adaptable. With these principles, you’re well on your way to becoming a market leader in your field.</p>
<h2 id="heading-6-how-to-build-productive-habits-daily-routines-that-propel-you-forward">6. How to Build Productive Habits: Daily Routines That Propel You Forward</h2>
<h3 id="heading-work-on-your-mind-and-body">Work on your mind and body</h3>
<p>To excel as a creator, it’s imperative to nurture not just your creative talents, but also the holistic aspects of your being - your mind, body, and spirit. Each element plays a crucial role in shaping your effectiveness and fulfillment in your creative journey.</p>
<h4 id="heading-mind-the-intellectual-dynamo">Mind: the intellectual dynamo</h4>
<p>Here are some ways to engage and develop your mind:</p>
<ul>
<li><strong>Eclectic Reading:</strong> Diversify your reading list. Both fiction and non-fiction books broaden your understanding and perspectives.</li>
<li><strong>Lifelong Learning:</strong> Engage in ongoing education through courses, workshops, and self-study to keep your mind agile and knowledgeable.</li>
<li><strong>Brain Challenges:</strong> Stimulate your intellect with puzzles, strategy games, or learning new skills, to keep your mind sharp.</li>
</ul>
<h4 id="heading-body-the-vital-foundation">Body: the vital foundation</h4>
<p>Taking care of your body is important, so here are some tips to help you out:</p>
<ul>
<li><strong>Consistent Exercise:</strong> Regular physical activity, whether it's gym workouts, yoga, or outdoor sports, is crucial for maintaining high energy levels and mental sharpness.</li>
<li><strong>Balanced Diet:</strong> Nourish your body with foods that enhance cognitive and physical performance.</li>
<li><strong>Restorative Sleep:</strong> Prioritize sufficient and quality sleep for your body’s recovery and optimal functioning.</li>
</ul>
<h4 id="heading-spirit-the-core-of-your-creative-essence">Spirit: the core of your creative essence</h4>
<p>This one might seem less tangible, but it's key for your mental health and overall happiness. Here are some tips to help you nurture your spirit:</p>
<ul>
<li><strong>Mindfulness and Meditation:</strong> Incorporate practices like meditation and deep breathing to maintain emotional balance and inner peace.</li>
<li><strong>Nature Connection:</strong> Regularly spend time in nature to rejuvenate your spirit and spark creativity.</li>
<li><strong>Engage in Passionate Activities:</strong> Allocate time for hobbies or interests that fulfill you spiritually.</li>
<li><strong>Spiritual Reading:</strong> Incorporate spiritual or philosophical texts that resonate with your beliefs. This practice can offer profound insights and strengthen your personal values and convictions. Stay true to your beliefs and let them guide you in your creative endeavors.</li>
</ul>
<h3 id="heading-prioritize-with-precision">‌‌Prioritize with Precision</h3>
<p>Focus on what really matters. Every task you take on should be evaluated for its impact on your goals. If it doesn't significantly move you forward, drop it. </p>
<p>It's not about how much you do, but the value each task adds. Utilize Steven Covey's <a target="_blank" href="https://www.indeed.com/career-advice/career-development/covey-time-management-matrix">Time Management Matrix</a> to identify tasks that are important and urgent, and prioritize them.</p>
<ul>
<li><strong>Technique:</strong> Utilize the Eisenhower Box to categorize tasks into urgent, important, both, or neither.</li>
<li><strong>Actionable Step:</strong> Daily, list your tasks and categorize them in each box. Focus on urgent and important tasks first.</li>
<li><strong>Tip:</strong> Regularly review tasks in the 'neither' category – consider delegating or eliminating them.</li>
</ul>
<h3 id="heading-integrate-effective-breaks">Integrate Effective Breaks</h3>
<p>‌‌Being productive doesn't mean working endlessly. In fact, smart breaks can boost your efficiency. </p>
<p>Regular pauses are essential to refresh your mind and body. They ensure you're not just busy, but effective. Incorporate breaks into your routine, be it a walk, a casual chat, or a moment to relax. Life is more than work – balance is key.</p>
<ul>
<li><strong>Technique:</strong> Use the Pomodoro Technique – 25 minutes of focused work followed by a 5-minute break.</li>
<li><strong>Actionable Step:</strong> Set a timer for each work session and break. Use breaks for physical activity or relaxation.</li>
<li><strong>Tip:</strong> After four Pomodoros, take a longer 15-30 minute break.</li>
</ul>
<h3 id="heading-establish-a-distraction-free-zone">Establish a Distraction-Free Zone</h3>
<p>‌‌Identify what's hindering your productivity. It could be a cluttered workspace, constant notifications, or interruptions. Find your productivity pitfalls and eliminate them. Test different environments and make necessary adjustments. A distraction-free space is crucial for peak performance.</p>
<ul>
<li><strong>Technique:</strong> Identify your primary distractions and eliminate them.</li>
<li><strong>Actionable Step:</strong> Create a 'distraction list' and tackle each item – for example, turn off notifications, clear your desk.</li>
<li><strong>Tip:</strong> Use noise-canceling headphones or white noise apps to maintain focus in noisy environments.</li>
</ul>
<h3 id="heading-harness-your-passion">Harness Your Passion</h3>
<p>What excites you? Use that as your driving force. If empowering others ignites your passion, let that energy fuel your work. Start by identifying common challenges and address them with enthusiasm. Work driven by passion is never dull.</p>
<ul>
<li><strong>Technique:</strong> Align tasks with what motivates you.</li>
<li><strong>Actionable Step:</strong> Identify tasks that align with your passions and prioritize them in your schedule.</li>
<li><strong>Tip:</strong> For less enjoyable tasks, find ways to connect them to your broader goals or passions.</li>
</ul>
<h3 id="heading-guard-your-time">Guard Your Time</h3>
<p>‌‌In today’s connected world, constant availability can hinder productivity. Set boundaries to minimize disruptions during work. This might mean turning off your phone or setting specific times for email. It’s about making yourself less accessible during focused work periods.</p>
<ul>
<li><strong>Technique:</strong> Allocate specific times for different types of tasks.</li>
<li><strong>Actionable Step:</strong> Plan your day with time blocks for deep work, communication, breaks, and personal time.</li>
<li><strong>Tip:</strong> Use digital calendars with alerts to remind you of the next time block.</li>
</ul>
<h3 id="heading-maximize-small-moments">Maximize Small Moments</h3>
<p>‌‌Every day is filled with brief moments of unused time. Use these wisely. Whether it's listening to a podcast during a commute or planning your day while waiting for a meeting, these moments add up. Turn these small pockets of time into opportunities for growth and learning.</p>
<ul>
<li><strong>Technique:</strong> Identify small pockets of time and use them productively.</li>
<li><strong>Actionable Step:</strong> Keep a list of quick tasks or learning materials handy for these moments.</li>
<li><strong>Tip:</strong> Use commuting time for audiobooks or podcasts related to your field.</li>
</ul>
<h3 id="heading-set-deadlines">Set Deadlines</h3>
<p>‌‌Define clear timelines for your tasks. Work tends to expand to fill the time available, so set deadlines to maintain focus and efficiency. Deadlines create a sense of urgency, pushing you to complete tasks more quickly and efficiently.</p>
<ul>
<li><strong>Technique:</strong> Set specific deadlines for each task.</li>
<li><strong>Actionable Step:</strong> For each task, decide a completion date and note it down.</li>
<li><strong>Tip:</strong> Publicly commit to deadlines where possible to increase accountability.</li>
</ul>
<h3 id="heading-embrace-automation">Embrace Automation</h3>
<p>‌‌Use technology to handle repetitive tasks. Whether it's email filtering, automated bill payments, or social media scheduling, find ways to automate the mundane. This frees up more time for creative and high-value work.</p>
<ul>
<li><strong>Technique:</strong> Automate repetitive and low-value tasks.</li>
<li><strong>Actionable Step:</strong> Identify tasks you can automate using tools like email filters, bill autopay, or content scheduling.</li>
<li><strong>Tip:</strong> Regularly review and update your automation tools for efficiency.</li>
</ul>
<p>‌‌Productive habits are about working smarter, not just harder. By focusing on impactful tasks, taking smart breaks, creating distraction-free environments, leveraging your passion, setting boundaries, using small moments effectively, establishing deadlines, and automating routine tasks, you pave the way for enhanced productivity. </p>
<p>These habits are your toolkit for not just achieving more, but for achieving what truly matters. Embrace them, and transform your work and life.</p>
<h2 id="heading-7-strategic-approaches-how-to-navigate-multiple-routes-to-achieve-your-goals">7. Strategic Approaches: How to Navigate Multiple Routes to Achieve Your Goals</h2>
<p>As a creator or student, your journey towards your goals is like navigating a city with multiple routes. Each path offers unique perspectives and opportunities, making the journey as significant as the destination. </p>
<p>Remember, having multiple strategies to reach your goal doesn't dilute your focus – it enhances your resilience and adaptability.</p>
<h3 id="heading-expand-your-strategic-horizons">Expand Your Strategic Horizons</h3>
<h4 id="heading-broaden-your-approach">Broaden Your Approach:</h4>
<p>Understand that each goal, like a multifaceted gem, can be approached from various angles. </p>
<p>For students, diversify your skillset beyond academics. Engage in extracurricular activities, internships, or part-time roles that align with your career aspirations. </p>
<p>For creators, explore different mediums and platforms. If you’re a writer, consider podcasts, webinars, or video content to broaden your audience reach.</p>
<h4 id="heading-showcase-and-build-your-skills">Showcase and Build Your Skills:</h4>
<p>Leverage digital platforms to demonstrate your talents. A YouTube channel, blog, or social media can be powerful tools for showcasing your skills and engaging with your audience or potential employers. </p>
<p>Create a portfolio of your work, be it academic projects, personal creations, or professional assignments. This not only displays your skills but also your journey and growth.</p>
<h4 id="heading-the-intersection-of-goals-and-financial-stability">The Intersection of Goals and Financial Stability:</h4>
<p>Financial acumen is key. Understand how to manage and grow your finances, regardless of your career stage. </p>
<p>For creators, think about monetizing your skills through online courses, merchandise, or consulting services. Students can look into scholarships, grants, or fellowship programs that offer both financial aid and valuable experience.</p>
<h4 id="heading-creating-multiple-income-streams">Creating Multiple Income Streams:</h4>
<p>Diversify your income sources. This might mean having a side hustle, investing in stocks, or starting a small online business. Use your skills to create passive income sources. </p>
<p>For instance, a photographer can sell prints online, while a programmer can develop and sell software or apps.</p>
<h4 id="heading-leveraging-personal-branding">Leveraging Personal Branding:</h4>
<p>Build a strong personal brand that reflects your skills, values, and vision. This can open doors to opportunities and collaborations. Engage with your community. Building a network isn’t just about meeting people – it’s about creating relationships that can lead to mutual growth and opportunities.</p>
<h3 id="heading-learn-to-navigate-challenges-and-opportunities">Learn to Navigate Challenges and Opportunities</h3>
<h4 id="heading-embrace-lifelong-learning">Embrace Lifelong Learning:</h4>
<p>Stay curious and committed to learning. The world is constantly evolving, and so should your knowledge and skills. </p>
<p>Attend workshops, enroll in online courses, or join professional groups in your field. This not only enhances your skillset but also keeps you connected and relevant.</p>
<h4 id="heading-strategic-goal-setting">Strategic Goal Setting:</h4>
<p>Set SMART goals – Specific, Measurable, Achievable, Relevant, Time-bound. This framework helps you stay focused and measure your progress. Break down larger goals into smaller, manageable tasks. This makes the process less overwhelming and more achievable.</p>
<h4 id="heading-adapt-to-change">Adapt to Change:</h4>
<p>Stay flexible and adaptable. The path to your goals may need to be adjusted as circumstances change. Be open to new ideas and approaches. Sometimes, the most unconventional path can lead to the most rewarding outcomes.</p>
<h4 id="heading-cultivate-resilience-and-persistence">Cultivate Resilience and Persistence:</h4>
<p>Understand that setbacks are part of the journey. Learn from failures and use them as stepping stones. Maintain a growth mindset. View challenges as opportunities to grow and improve.</p>
<p>In your quest for success, whether as a student, a creator, or any professional, remember that there are myriad ways to reach your goals. Embrace the journey with its multitude of paths. </p>
<p>By being adaptable, embracing continuous learning, diversifying your strategies, and staying resilient, you equip yourself for not just achieving your goals, but surpassing them. </p>
<p>The journey towards success is rarely a straight line. It's usually a rich tapestry of experiences, learning, and growth. Embrace this dynamic path, and you'll find that the journey itself becomes part of your success story.</p>
<h2 id="heading-8-creators-confidence-how-to-trust-your-gut-to-make-game-changing-decisions">8. Creator’s Confidence: How to Trust Your Gut to Make Game-Changing Decisions</h2>
<p>Confidence, at its essence, is the deep-seated belief that you are capable of achieving what you set out to do. As a creator, cultivating robust self-confidence is not optional – it's a necessity. </p>
<p>Think of confidence as a muscle that needs consistent training. How do you train it? By living up to your word, day in and day out. If you commit to something, ensure you follow through. Keep to-do lists manageable and actionable. Engage in activities that build both mental and physical strength, such as exercising, meditating, and journaling. Accept reality as it is, not as you wish it to be.</p>
<h3 id="heading-key-components-of-confidence">Key Components of Confidence</h3>
<ul>
<li><strong>Self-belief</strong>: Confidence is about having a positive and realistic belief in your abilities. Trust that you can face challenges, make decisions, and achieve your goals.</li>
<li><strong>Self-esteem</strong>: Linked closely to confidence, self-esteem is your sense of self-worth and value. Maintaining a healthy level of self-esteem is vital for confidence.</li>
<li><strong>Positive self-image</strong>: Confident people often possess a positive self-image. They accept their imperfections and focus on their strengths.</li>
<li><strong>Self-assuredness</strong>: This is reflected in behavior. Confident people appear composed and poised, even in difficult situations.</li>
<li><strong>Resilience</strong>: The ability to recover from setbacks, learning, and growing from these experiences is a hallmark of confidence.</li>
<li><strong>Self-efficacy</strong>: Believing in your ability to accomplish specific tasks or goals boosts confidence in those areas.</li>
<li><strong>Social confidence</strong>: Being comfortable in social settings, communicating effectively, and forming positive relationships are aspects of social confidence.</li>
<li><strong>Trust in decision-making</strong>: Confident people trust their judgment and are less swayed by external opinions.</li>
</ul>
<h3 id="heading-how-to-overcome-insecurity-myths">How to Overcome Insecurity Myths</h3>
<p>There's a common misconception that everyone is inherently insecure. While it's normal to have insecurities, accepting them as unchangeable is a mistake. It's crucial to understand that it's okay to start with insecurities, but you shouldn't stagnate there. Try to evolve from weakness to strength.</p>
<h4 id="heading-strategies-for-building-confidence">Strategies for Building Confidence</h4>
<ol>
<li><strong>Rack up Wins</strong>: Engage in activities where you can achieve victories, big or small. Success breeds confidence. Avoid activities like excessive gaming that don't translate to real-world confidence.</li>
<li><strong>Have Options</strong>: In both personal and professional life, having options boosts your confidence. It allows you to walk away from less desirable situations, knowing you have alternatives.</li>
<li><strong>Be Dangerous</strong>: This doesn't mean being physically threatening, but rather being formidable in your skills and capabilities. Train physically and mentally to be strong and articulate.</li>
<li><strong>Far from Weak</strong>: Aim to be strong in all key areas of your life. This means improving 1% every day, seeking knowledge, and relentlessly pursuing your goals.</li>
<li><strong>Solve Problems</strong>: Enhance your problem-solving skills. Big problems shouldn't intimidate you. The size of your problems often reflects the size of your capabilities.</li>
<li><strong>Intentionality</strong>: Act, speak, and live with intention. Understand the why behind your actions and words. This clarity breeds confidence.</li>
</ol>
<h4 id="heading-practical-takeaways">Practical Takeaways</h4>
<ul>
<li>Develop routines that reinforce confidence-building habits.</li>
<li>Focus on small, daily victories to cultivate a sense of achievement.</li>
<li>Engage in activities that challenge both your mind and body.</li>
<li>Practice decision-making in various aspects of your life to build trust in your judgment.</li>
<li>Reflect on your progress regularly, acknowledging growth and areas for improvement.</li>
</ul>
<p>Confidence is not just a trait you are born with – it's a skill developed through practice, resilience, and intentionality. By following these practical steps and understanding the components of confidence, you can trust your gut to make game-changing decisions, both in your personal and professional life. Remember, confidence is a journey, not a destination. Keep striving, keep learning, and keep growing.</p>
<h2 id="heading-9-have-a-10-year-plan-how-to-craft-plans-that-shape-the-future">9. Have a 10 Year Plan: How to Craft Plans That Shape the Future</h2>
<p>Embarking on a 10-year journey requires a blend of vision, strategy, and adaptability. It's about crafting a roadmap that aligns your daily actions with your long-term aspirations. </p>
<p>A well-structured 10-year plan acts as a guiding star, helping you navigate through life's complexities with clarity and purpose.</p>
<h3 id="heading-what-is-a-10-year-plan">What is a 10-Year Plan?</h3>
<p>A 10-year plan is not just a list of lofty goals. It's a strategic outline that bridges the gap between where you are now and where you aspire to be. It's a blend of practicality and ambition, infused with personal values and aspirations. </p>
<p>This plan should be dynamic, allowing for adjustments as you evolve and as circumstances change.</p>
<p>Let's now discuss some strategies you can employ to make your own 10-year plan:</p>
<h4 id="heading-identify-core-values-and-life-domains">Identify core values and life domains</h4>
<p>Begin by reflecting on your core values – these are the principles that will anchor your plan. Consider aspects like health, relationships, career, personal growth, and financial stability. </p>
<p>What do these areas look like in your ideal future? Establish clear, long-term objectives for each domain.</p>
<h4 id="heading-set-smart-goals">Set SMART goals</h4>
<p>Each goal within your 10-year plan should adhere to the SMART framework (Specific, Measurable, Achievable, Relevant, and Time-Bound). This ensures that your goals are not just dreams, but actionable targets. </p>
<p>For instance, instead of vaguely aiming to be financially stable, set a specific goal like achieving a certain net worth or being debt-free within a defined timeframe.</p>
<h4 id="heading-break-down-the-decade">Break down the decade</h4>
<p>Ten years may sound like a long time, the distant future. But it'll go by faster than you think. Here are some tips to help you break down this 10-year block into more approachable chunks.</p>
<ol>
<li><strong>Set yearly milestones</strong>: Divide your 10-year goals into annual milestones. This breakdown makes the journey more manageable and keeps you consistently on track.</li>
<li><strong>Do quarterly reviews</strong>: Every three months, assess your progress. Are you moving closer to your goals? What adjustments are needed?</li>
<li><strong>Pick a monthly focus</strong>: Assign each month a specific focus area. This could be a skill to learn, a habit to develop, or a small project that aligns with your long-term goals.</li>
<li><strong>Decide on weekly actions</strong>: Every week, list down tasks that contribute to your monthly focus. These actions are the building blocks of your 10-year plan.</li>
<li><strong>Perform daily habits</strong>: Incorporate daily habits that directly or indirectly support your long-term objectives. Consistency in these small actions accumulates significant results over time.</li>
</ol>
<h4 id="heading-embrace-flexibility">Embrace flexibility</h4>
<p>While it's crucial to have a structured plan, it's equally important to be adaptable. Life can bring unexpected changes, and your plan should have the flexibility to accommodate these shifts. </p>
<p>Regularly revisit and revise your plan to reflect your current circumstances and evolving aspirations.</p>
<h4 id="heading-use-tracking-and-accountability-tools">Use tracking and accountability tools</h4>
<p>Utilize tools like planners, apps, or digital platforms to track your progress. Regularly documenting your journey not only keeps you accountable but also provides valuable insights into your patterns and areas for improvement.</p>
<h4 id="heading-leveraging-community-support">Leveraging community support</h4>
<p>Share your 10-year vision with trusted friends, family, or mentors. Their support, advice, and perspective can be invaluable. </p>
<p>Also consider joining groups or communities where members share similar goals – the collective wisdom and encouragement can be a powerful motivator.</p>
<h3 id="heading-a-decade-of-purposeful-growth">A Decade of Purposeful Growth</h3>
<p>Crafting a 10-year plan is an investment in yourself. It's about envisioning a future where your actions and decisions are driven by purpose and intention. </p>
<p>As you embark on this decade-long journey, remember that the ultimate goal is not just to achieve specific outcomes, but to experience growth, fulfillment, and a deeper understanding of yourself and your place in the world.</p>
<p>Remember, the essence of a 10-year plan lies not in rigid adherence to a predetermined path, but in the continuous pursuit of personal growth and the realization of your potential.</p>
<h2 id="heading-10-play-the-game-on-your-terms-the-fastest-way-to-achieve-whatever-you-want">10. Play the Game on Your Terms: the Fastest Way to Achieve Whatever You Want</h2>
<p>Charting your own course in life and career is not just a choice, it's a necessity. This chapter, 'Playing the Game on Your Terms', is about seizing that control and living life by your rules. It's an empowering journey that rejects the one-size-fits-all blueprint for success and instead, carves out a path that aligns with your unique vision, values, and aspirations.</p>
<p>Success, in this context, is a deeply personal concept. It’s about defining what truly matters to you, not just adhering to societal norms or expectations. This chapter encourages you to harness your strengths and interests, shaping them into a powerful force that drives your life and career forward.</p>
<p>Take, for instance, the quest for a balanced life. Many of us struggle with time management, often sacrificing personal health, happiness, or family time. By choosing to steer your own ship – say, starting a business, delegating tasks, or seeking investments – you can reshape your life. Yes, it might require intense effort initially, but the long-term gains of happiness, fitness, or more family time are invaluable.</p>
<p>Remember, without your own goals, mission, or vision, life can quickly become a directionless drift. This chapter is about anchoring yourself in your own truth and sailing confidently towards your definition of success.</p>
<h3 id="heading-craft-your-unique-strategy-principles-and-practices">Craft Your Unique Strategy: Principles and Practices</h3>
<p>The first step in playing the game on your terms is to define what success means to you personally. This definition should be grounded in your values, aspirations, and life goals. It's about aligning your actions with what genuinely matters to you, rather than conforming to external expectations or predefined paths.</p>
<ul>
<li><strong>Defining success:</strong> Begin by introspecting on what you value most. Is it professional achievement, personal growth, financial stability, or something else? Define what each of these means in practical, achievable terms.</li>
<li><strong>Goal setting:</strong> Translate these values into concrete goals. These should be specific, measurable, achievable, relevant, and time-bound (SMART). This process turns abstract concepts into actionable steps.</li>
</ul>
<h3 id="heading-navigate-emotional-complexity-in-decision-making">Navigate Emotional Complexity in Decision-Making</h3>
<p>Emotional intelligence plays a pivotal role in personal and professional decision-making. It's about understanding your emotional responses and how they impact your choices. </p>
<p>So what are some strategies to help you manage emotions effectively, ensuring they contribute positively to your decision-making process?</p>
<ul>
<li><strong>Emotional awareness:</strong> Cultivate an understanding of your emotional triggers and responses. This awareness enables you to make decisions that are not clouded by temporary emotional states.</li>
<li><strong>Responsive decision-making:</strong> Develop the skill to respond to situations based on informed choices rather than impulsive reactions. This approach leads to more consistent and aligned decision-making.</li>
</ul>
<h3 id="heading-adapt-to-change-flexibility-in-strategy">Adapt to Change: Flexibility in Strategy</h3>
<p>In a rapidly changing environment, adaptability is key. Here are some tips to help you develop a flexible mindset, allowing you to adjust and refine your strategies as circumstances evolve.</p>
<ul>
<li><strong>Strategic flexibility:</strong> Learn to recognize when a change in strategy is needed. This may involve pivoting in response to new opportunities or challenges.</li>
<li><strong>Continuous learning:</strong> Embrace the process of continuous learning and growth. This ensures that your strategies and approaches remain relevant and effective.</li>
</ul>
<h3 id="heading-embrace-innovation-and-risk-taking">Embrace Innovation and Risk-Taking</h3>
<p>Innovation is at the heart of playing the game on your terms. You'll need to learn how to foster creativity and innovation in your approach, and take calculated risks when appropriate.</p>
<ul>
<li><strong>Creative problem-solving:</strong> Develop skills in creative thinking and problem-solving. This involves looking at challenges from different perspectives and finding unique solutions.</li>
<li><strong>Calculated risk-taking:</strong> Understand the importance of taking risks. Learn to evaluate potential risks and rewards, making informed decisions that can lead to significant advancements.</li>
</ul>
<h3 id="heading-practice-tactical-thinking-and-competition">Practice Tactical Thinking and Competition</h3>
<p>Understanding your competitive landscape is crucial. This involves not only recognizing potential competitors but also identifying opportunities where you can excel.</p>
<ul>
<li><strong>Strategic analysis:</strong> Conduct a thorough analysis of your industry or field. Understand where you stand and where you can differentiate yourself.</li>
<li><strong>Competitive advantage:</strong> Identify your unique selling points or strengths. Leverage these to create a niche or advantage in your respective area.</li>
</ul>
<h3 id="heading-align-actions-with-long-term-goals">Align Actions with Long-Term Goals</h3>
<p>Consistency in action is vital for achieving long-term goals. Make sure that your daily actions and decisions are aligned with your broader objectives.</p>
<ul>
<li><strong>Regular reviews:</strong> Implement a system of regular reviews to ensure that your actions are in line with your goals.</li>
<li><strong>Adjustment and refinement:</strong> Be prepared to adjust your tactics and strategies in response to feedback and results.</li>
</ul>
<h3 id="heading-build-supportive-networks">Build Supportive Networks</h3>
<p>The people around you can significantly influence your journey. Take the time to build a network of supporters, mentors, and collaborators who align with and support your vision.</p>
<ul>
<li><strong>Strategic Networking:</strong> Seek out and build relationships with people who can offer guidance, support, and collaboration opportunities.</li>
<li><strong>Community Building:</strong> Engage with or create communities that share your values and goals. This can provide a supportive environment for growth and learning.</li>
</ul>
<h3 id="heading-develop-resilience-and-overcome-setbacks">Develop Resilience and Overcome Setbacks</h3>
<p>Resilience is a critical aspect of personal and professional development. It's about developing the ability to overcome challenges and setbacks.</p>
<ul>
<li><strong>Learning from failures:</strong> View failures as learning opportunities. Analyze what went wrong and how you can improve in the future.</li>
<li><strong>Building mental and emotional strength:</strong> Develop strategies to maintain your focus and motivation, even in the face of difficulties.</li>
</ul>
<p>Playing the game on your terms is about taking control of your journey towards success. It requires a deep understanding of your goals, the flexibility to adapt, the courage to innovate and take risks, and the resilience to overcome challenges. </p>
<p>Remember, your path to success is unique to you – define it, pursue it, and achieve it on your terms.</p>
<h2 id="heading-11-the-power-of-networking-how-to-build-connections-that-propel-your-vision">11. The Power of Networking: How to Build Connections That Propel Your Vision</h2>
<p>In the dynamic world of creation, where innovation and collaboration intersect, I can't overstate the power of networking. </p>
<p>For creators in any field, be it art, technology, business, or entertainment, having a robust network is not just a supplementary asset but a fundamental necessity for growth and success. While creators are often viewed as solitary geniuses, the truth is that the most successful ones are surrounded by a web of connections that propels them forward.</p>
<p>Think of your network as a living, breathing entity that extends far beyond the confines of your immediate professional circle. It includes everyone from headhunters who can open doors to new opportunities, to peers who can provide referrals, and even to potential partners and investors for your entrepreneurial ventures. </p>
<p>The strength of your network can be the difference between a stalled career and one that soars to new heights.</p>
<p>In this digital age, where boundaries are blurred and collaboration can happen across continents, underestimating the power of networking is a mistake too costly to make. It's not just about having a long list of contacts – it's about nurturing relationships that are mutually beneficial, where support and value flow in both directions.</p>
<p>As a creator, your network is your gateway to new ideas, opportunities, and platforms. Whether it's getting insider advice, landing your dream project, or kickstarting a venture, your network is the key.</p>
<p>In this chapter, we will explore the intricacies of building and leveraging a network that not only supports your current endeavors but also paves the way for future success. It’s time to shift the perspective: view networking not as a chore, but as an exciting journey of building a community around your creative aspirations.</p>
<h3 id="heading-how-to-build-a-strong-foundation">How to Build a Strong Foundation</h3>
<p>Networking is about building a solid base for your professional and personal growth. It's not just about whom you know, but who knows you and values your connection. </p>
<p>A strong foundation in networking is based on your skills, reputation, and the ability to provide value to others. It’s about being a top performer in your field and enhancing your visibility through personal branding, public speaking, and other skills. </p>
<p>This visibility opens doors and creates opportunities for meaningful connections. And while it may be easier for a top engineer to attract more networking opportunities than one who hasn’t made their mark yet, you don't have to be an expert to network.</p>
<p>Because it’s not just about skill and experience. It's also about being proactive in offering value and never expecting immediate returns. This approach builds an unshakeable foundation.</p>
<h3 id="heading-the-power-of-generosity-and-loyalty-in-networking">The Power of Generosity and Loyalty in Networking</h3>
<p>True networking centers on the principle of "give and take." Be generous with your time, resources, and support, but also be selective. Invest in relationships where mutual respect and benefit exist. Understand the balance of generosity, especially with those who are capable of reciprocation but choose not to. Your network's worth is significantly enhanced when there is a balance of giving and receiving.</p>
<h3 id="heading-developing-patience-and-sociability">Developing Patience and Sociability</h3>
<p>Success in networking doesn’t happen overnight. It requires patience and consistent effort. Like Hillary Clinton shaking thousands of hands, understand that networking is a marathon, not a sprint. Cultivate relationships daily and always be on the lookout for new connections.</p>
<h3 id="heading-practical-steps-to-effective-networking">Practical Steps to Effective Networking</h3>
<h4 id="heading-ping-constantly">Ping constantly</h4>
<p>In today's digital world, staying in touch is easier than ever. Use social media to your advantage by liking posts, commenting, and sending direct messages. These small actions keep relationships warm and remind your contacts of your presence.</p>
<h4 id="heading-never-eat-alone">Never eat alone</h4>
<p>Make the most of your everyday activities by including others. Invite someone to join you for a meal, a workout, or a casual meeting. This practice strengthens bonds and creates new networking opportunities.</p>
<h4 id="heading-be-interesting">Be interesting</h4>
<p>Continuously learn new things and share your knowledge. This makes you an appealing connection and someone people want to know.</p>
<h4 id="heading-follow-up-on-meetings">Follow up on meetings</h4>
<p>Always follow up with a message or an email after meeting someone new. Thank them for their time, and follow up on something interesting you discussed. This simple gesture can turn a casual meeting into a lasting connection.</p>
<h4 id="heading-connect-with-connectors">Connect with connectors</h4>
<p>Identify and work on building relationships with super-connectors, people who have a vast network across various industries. They can significantly broaden your networking scope.</p>
<h4 id="heading-attend-conferences">Attend conferences</h4>
<p>Attend industry conferences or events related to your field of interest. These are prime networking opportunities where everyone is looking to make connections.</p>
<h4 id="heading-learn-how-to-make-small-talk">Learn how to make small talk</h4>
<p>Develop the skill of engaging in light, interesting conversations. This opens the door to deeper, more meaningful interactions.</p>
<h4 id="heading-overcome-the-fear-of-rejection">Overcome the fear of rejection</h4>
<p>Treat networking as a numbers game. The more people you reach out to, the more likely you are to make meaningful connections. Embrace rejection as a part of the process and learn from each interaction.</p>
<h4 id="heading-build-networks-proactively">Build networks proactively</h4>
<p>Start building your network now, not when you need it. Proactive networking builds trust and prevents you from being seen as someone who only reaches out when in need.</p>
<h4 id="heading-identify-and-utilize-relationship-glues">Identify and utilize relationship glues</h4>
<p>Discover shared interests or activities that can turn an acquaintance into a trusted friend or connection. These shared experiences create stronger bonds.</p>
<h4 id="heading-personal-branding-and-messaging">Personal branding and messaging</h4>
<p>Develop a strong personal brand that makes you a desirable connection. Your online and offline presence should communicate your skills, interests, and values. This visibility can attract connections and open doors to new opportunities.</p>
<p>By being proactive, generous, and focused on your goals, you can turn your network into a significant asset for both personal and professional growth. Remember, your network's strength lies not only in its size but in the quality of connections and the mutual value each connection brings.</p>
<h2 id="heading-12-risk-management-how-to-harness-uncertainty-for-game-changing-success">12. Risk Management: How to Harness Uncertainty for Game-Changing Success</h2>
<p>In the dynamic world of software development and technology, mastering risk management is essential for breakthrough innovation and success. </p>
<p>Think about the stories of tech powerhouses like Amazon, Apple, and Google. They evolved from modest starts to global dominators, emphasizing a vital truth: calculated risk-taking is integral to exceptional achievements.</p>
<p>For developers, risk management means steering through uncertainty and unpredictability, turning these into opportunities for remarkable advancements. </p>
<p>True innovation often involves not just inventing new technologies but reimagining and enhancing existing ones. It's about challenging established norms, diving deep into problem-solving, and venturing into new technological frontiers.</p>
<p>This chapter is crafted to provide developers with actionable strategies used by the most successful tech companies. It’s tailored to empower you with techniques ranging from obtaining deep customer insights to diversifying your development projects. </p>
<p>You’ll explore methods like conducting comprehensive market research, using advanced predictive algorithms, practicing prudent financial management, and developing robust contingency plans. You'll also learn about intimately understanding your user base, a crucial aspect of developing successful software.</p>
<p>The aim here is twofold: to inspire you to embrace the uncertainties inherent in technology and to equip you with practical tools to turn risks into game-changing innovations. </p>
<p>Whether you're an aspiring developer, a tech entrepreneur, or a leader in the tech industry, your journey in effective risk management starts with the insights from this chapter.</p>
<h3 id="heading-identify-and-analyze-potential-risks">Identify and Analyze Potential Risks</h3>
<p>The first step in risk management is the identification and analysis of potential risks. This involves understanding the various factors that could negatively impact your project and evaluating their likelihood and potential damage. </p>
<p>Whether it’s market volatility, technological changes, or audience preferences, having a clear understanding of these risks allows you to prepare adequately and respond effectively.</p>
<p>Here are some techniques to help you do this:</p>
<ul>
<li><strong>SWOT analysis:</strong> Regularly conduct SWOT analyses to gauge the health and potential of your projects.</li>
<li><strong>Stay alert:</strong> Remain vigilant to new technologies, market shifts, and audience trends that could pose risks.</li>
<li><strong>Risk register:</strong> Keep a log of identified risks to monitor and analyze them over time.</li>
</ul>
<h3 id="heading-swot-analysis">SWOT Analysis</h3>
<p>SWOT analysis is a strategic planning tool used to evaluate the <strong>S</strong>trengths, <strong>W</strong>eaknesses, <strong>O</strong>pportunities, and <strong>T</strong>hreats involved in a project or a business venture. It involves specifying the objective of the project or business and identifying the internal and external factors that are favorable and unfavorable to achieve that objective. </p>
<p>Let's break down each component:</p>
<ol>
<li><strong>Strengths</strong>: These are internal attributes of the company or project that are helpful to achieving the objective. They could include resources, capabilities, or any other advantage relative to competitors.<br>For example, a company might have a dedicated and skilled workforce, innovative technology, strong brand recognition, or superior customer service.</li>
<li><strong>Weaknesses</strong>: Internal attributes that are harmful to achieving the objective. These might include lack of expertise, limited resources, poor location, or inferior technology.<br>For instance, a company might struggle with outdated production equipment, high staff turnover, or limited financial resources.</li>
<li><strong>Opportunities</strong>: External conditions that could be exploited to achieve the objective. These might include market growth, changes in consumer lifestyle, technological advances, or regulatory changes.<br>For example, a tech company might find an opportunity in a new emerging market or a shift in consumer preferences that aligns with their product.</li>
<li><strong>Threats</strong>: External conditions that could damage the business's performance. This could include competition, changes in market requirements, technological changes, or adverse economic trends. For instance, a new competitor entering the market or a change in consumer behavior due to economic downturn can pose a threat.</li>
</ol>
<h4 id="heading-how-to-conduct-a-swot-analysis">How to Conduct a SWOT Analysis:</h4>
<ul>
<li>Define the objective of your project or business.</li>
<li>Identify internal strengths and weaknesses. This might involve employee surveys, financial analysis, and evaluation of processes and customer feedback.</li>
<li>Analyze the external environment for opportunities and threats, which might include market research, analyzing competitor strategies, and staying updated with industry trends.</li>
</ul>
<h4 id="heading-examples-of-identifying-risks-and-mitigation-strategies">Examples of Identifying Risks and Mitigation Strategies:</h4>
<ul>
<li><strong>Risks in Strengths</strong>: Over-dependence on a key resource (like a skilled employee) can be risky if that resource is lost. Mitigation could involve cross-training staff or developing backup resources.</li>
<li><strong>Risks in Weaknesses</strong>: For instance, a lack of digital presence in a business can be a weakness. Mitigating this might involve investing in digital marketing and enhancing online visibility.</li>
<li><strong>Risks in Opportunities</strong>: An emerging market might have hidden risks like cultural differences or unknown regulatory environments. Mitigating this could involve conducting thorough market research or forming local partnerships.</li>
<li><strong>Risks in Threats</strong>: For instance, a technological change making your product obsolete. Mitigation could involve continuous innovation and keeping a keen eye on industry trends.</li>
</ul>
<p>Remember, a SWOT analysis is most effective when it's honest, comprehensive, and continuously updated to reflect the changing environment.</p>
<h3 id="heading-know-your-customer-inside-and-out">Know Your Customer Inside and Out</h3>
<p>Understanding your audience is the cornerstone of risk management in any business. </p>
<p>Let’s take education as an example. Universities, major players in this sector, cater to a diverse student population. The key is to delve deeply into understanding your audience. What drives them? What are their pain points with current offerings? </p>
<p>For instance, students may be seeking more interactive and flexible learning options that traditional universities don’t provide. </p>
<p>By identifying these gaps and motivations, you can tailor your offerings to meet these specific needs, thereby mitigating the risk of irrelevance.</p>
<p>Here are some tips to help you learn more about your audience:</p>
<ul>
<li><strong>Conduct surveys and interviews:</strong> Actively engage with your audience through surveys and interviews. This direct interaction is key to grasping their preferences and pain points.</li>
<li><strong>Analyze feedback:</strong> Scrutinize the feedback you receive on social media, reviews, and direct communications. It's a goldmine for spotting trends and areas begging for improvement.</li>
<li><strong>Develop user personas:</strong> Craft detailed user personas that embody your target audience. These personas will be your North Star in guiding project development.</li>
</ul>
<h3 id="heading-diversify-creative-projects">Diversify Creative Projects</h3>
<p>Diversification is your safety net in the world of creation. Instead of pouring all your resources into one type of project or genre, spread out a bit. This approach not only fuels your creativity by exposing you to a range of ideas and techniques but also cushions you against financial downturns in one particular area. </p>
<p>For example, if you are in the film industry, don’t just stick to feature films – explore documentaries, short films, or even venture into digital platforms.</p>
<ul>
<li><strong>Explore multiple genres:</strong> Step outside your comfort zone and dabble in various creative fields or genres. It's not just about skill enhancement – it's about audience expansion.</li>
<li><strong>Allocate time and resources:</strong> Wisely distribute your time and resources across diverse projects. This is your hedge against putting all your eggs in one basket.</li>
<li><strong>Collaborate:</strong> Join forces with fellow creators. It's a win-win for sharing risks and reaping rewards.</li>
</ul>
<h3 id="heading-research-before-committing">Research Before Committing</h3>
<p>Before diving headfirst into a new project, conduct thorough research. Analyze current market trends, understand what your competitors are doing, and most importantly, get to know what your audience craves. </p>
<p>This step is crucial in gauging the potential success of your project and in making informed decisions that significantly reduce the risk of failure.</p>
<p>Here are some strategies to help you succeed:</p>
<ul>
<li><strong>Market analysis:</strong> Keep your finger on the pulse of market trends, consumer behavior, and industry buzz. It's essential for staying ahead of the curve.</li>
<li><strong>Competitor analysis:</strong> Always be aware of your competitors' moves. Their triumphs and setbacks are valuable lessons.</li>
<li><strong>Pilot testing:</strong> Before going all in, test your ideas on a small scale. It's like a sneak preview of your project's potential.</li>
</ul>
<h3 id="heading-use-predictive-tools">Use Predictive Tools</h3>
<p>Leverage technology and tools to predict outcomes. Market analysis, surveys, and trend forecasting are invaluable in understanding potential market responses to your project. </p>
<p>These tools provide data-driven insights that help you fine-tune your project before it even hits the market, thereby enhancing its chances of success.</p>
<ul>
<li><strong>Utilize analytics software:</strong> Tools like Google Analytics are your allies in dissecting web traffic and audience engagement patterns.</li>
<li><strong>Conduct surveys:</strong> Tap into survey tools to measure the pulse of your audience on upcoming projects.</li>
<li><strong>Stay informed:</strong> Subscribe to industry reports and stay abreast of trend forecasts. Knowledge is power.</li>
</ul>
<h3 id="heading-manage-your-financial-risk">Manage Your Financial Risk</h3>
<p>Prudent financial management is critical. Allocate your budget across various facets of your project, such as marketing, development, and equipment. This strategy helps in maintaining a balance and ensures that a setback in one area doesn’t capsize the entire project. </p>
<p>For instance, if you're launching a new app, balance your investment between development, user experience design, and marketing.</p>
<p>Here's how you can do that:</p>
<ul>
<li><strong>Budget planning:</strong> Devise a detailed budget for each project, earmarking funds for crucial areas like development and marketing.</li>
<li><strong>Monitor spending:</strong> Keep a vigilant eye on your expenses and be ready to tweak your budget when needed.</li>
<li><strong>Invest in growth:</strong> Reinvest your profits wisely to expand your reach and refine your skills.</li>
</ul>
<h3 id="heading-have-backup-plans">Have Backup Plans</h3>
<p>Always have a plan B. And possibly a plan C and D, too. The unpredictable nature of creative and business ventures makes it imperative to have contingency plans. If one project doesn’t pan out as expected, be ready to pivot or shift your focus to another venture. This approach ensures continuity and resilience in the face of setbacks.</p>
<ul>
<li><strong>Develop alternate ideas:</strong> Having a plan B (and C and D...) for when the unexpected happens gives you the confidence to take risks and try something new.</li>
<li><strong>Flexible scheduling:</strong> Maintain a fluid schedule that allows you to adapt and pivot as needed.</li>
<li><strong>Emergency fund:</strong> A financial cushion can soften the blow of unforeseen setbacks.</li>
</ul>
<h3 id="heading-incorporate-risk-assessment-into-the-decision-making-process">Incorporate Risk Assessment into the Decision Making Process</h3>
<p>Risk assessment should be an integral part of your decision-making process. This involves evaluating potential risks associated with a project and deciding how to approach them. </p>
<p>By analyzing risks in terms of probability and impact, you can make more informed decisions that align with your overall risk management strategy. This process ensures that every decision you make is weighed against potential risks, thus reducing the chances of unexpected setbacks.</p>
<p>Here are some tips to help you out:</p>
<ul>
<li><strong>Risk evaluation template:</strong> Create a standardized template to weigh risks for every significant decision.</li>
<li><strong>Consult with experts:</strong> For high-stake decisions, don't hesitate to seek advice from seasoned pros in your field.</li>
<li><strong>Regular reviews:</strong> Continuously revisit your decisions and their outcomes to sharpen your risk assessment acumen.</li>
</ul>
<h3 id="heading-develop-and-implement-a-risk-management-plan">Develop and Implement a Risk Management Plan</h3>
<p>A comprehensive risk management plan is pivotal for any successful project. This plan should include identifying potential risks, developing strategies to mitigate them, planning responses for when risks materialize, and setting up systems for ongoing risk monitoring. </p>
<p>This could involve risk reduction techniques, transferring risk (perhaps through insurance or partnerships), avoiding certain risks altogether, or even accepting some level of risk as part of the venture. The key is to have a strategy that aligns with your overall objectives and risk appetite.</p>
<p>This structured approach to managing risk not only prepares you for potential challenges but also ensures that you have clear steps to follow in mitigating them.</p>
<ul>
<li><strong>Document risks:</strong> Keep a comprehensive record of all potential risks and their countermeasures.</li>
<li><strong>Regular updates:</strong> Keep a close watch on these risks and evolve your risk management plan as your projects and the surrounding landscape change. </li>
<li><strong>Team involvement:</strong> Draw on the diverse perspectives of your team or collaborators for a more robust risk management strategy.</li>
<li><strong>Risk prioritization:</strong> Classify risks based on their potential impact and likelihood.</li>
<li><strong>Mitigation actions:</strong> For each risk, develop specific actions, whether it’s reduction, transfer, or acceptance.</li>
</ul>
<h3 id="heading-build-a-culture-of-accountability">Build a Culture of Accountability</h3>
<p>Cultivating a culture of accountability within your team or organization is crucial in managing risk effectively. This means fostering an environment where everyone feels responsible for identifying and addressing risks. </p>
<p>Such a culture encourages open communication about potential risks and proactive measures to mitigate them.</p>
<p>Here are some strategies to help you build such a culture:</p>
<ul>
<li><strong>Open communication:</strong> Foster a culture where risks and challenges are openly discussed. Don't play the blame game – focus on problem-solving.</li>
<li><strong>Responsibility assignment:</strong> Clearly assign risk management roles and responsibilities within your team so everyone know what they're responsible for.</li>
<li><strong>Celebrate accountability:</strong> Acknowledge and reward those who proactively manage and report risks.</li>
</ul>
<h3 id="heading-embrace-innovation-and-adaptability">Embrace Innovation and Adaptability</h3>
<p>Innovation and adaptability are your best allies in a dynamic and uncertain environment. Being open to new ideas and willing to adapt your approach in the face of changing circumstances can turn potential risks into opportunities. </p>
<p>Encourage a mindset of creative problem-solving and agility within your team. This can lead to innovative solutions that not only mitigate risks but also give you a competitive edge.</p>
<ul>
<li><strong>Foster creativity:</strong> Encourage free-flowing brainstorming sessions and out-of-the-box thinking.</li>
<li><strong>Adaptability training:</strong> Invest in activities or training that boost your adaptability to changing scenarios.</li>
<li><strong>Embrace change:</strong> Be open to modifying your strategies based on new insights or opportunities.</li>
</ul>
<h3 id="heading-learn-from-both-failure-and-success">Learn from Both Failure and Success</h3>
<p>Both success and failure offer invaluable lessons. Conducting failure analysis or post-mortem reviews on unsuccessful projects helps you understand what went wrong and how to avoid similar pitfalls in the future. </p>
<p>Similarly, analyzing successful projects can highlight key success factors and strategies that can be replicated or adapted in future ventures. </p>
<p>This continuous loop of learning and improvement is essential for long-term success in risk-laden environments.</p>
<ul>
<li><strong>Failure analysis:</strong> After a setback, meticulously dissect what went wrong and strategize for better outcomes in the future.</li>
<li><strong>Celebrate successes:</strong> Analyze your triumphs to understand what clicked and how you can replicate it.</li>
<li><strong>Continuous learning:</strong> Commit to ongoing education and skill enhancement to remain agile and informed.</li>
</ul>
<p>As creators and innovators, our path is inherently intertwined with risk. The strategies outlined above are not mere suggestions – they are essential components of a creator's toolkit. </p>
<p>Each strategy is designed to provide you with the clarity and confidence needed to navigate the uncertain terrain of creativity and business. By embracing these methodologies, you are preparing for risks while actively shaping your journey towards success. </p>
<p>These actionable steps are your roadmap to mastering the art of risk and turning challenges into opportunities for growth and innovation.</p>
<h2 id="heading-13-how-to-turn-failures-to-wins-learning-from-setbacks-for-greater-success"><strong>13.</strong> How to Turn Failures to Wins: Learning from Setbacks for Greater Success</h2>
<p>In the relentless pursuit of creation, failure is not just a possibility, it's an inevitability. For every creator, artist, entrepreneur, or dreamer, the journey is riddled with setbacks and losses. But these are not signs of defeat. They are the crucibles in which resilience, flexibility, and success are forged. </p>
<p>The ability to turn failures into wins is not just a skill but a necessity. The battlefield is not just in the external world of competition and market forces. It's also internal, within the realms of one's mind and emotions. </p>
<p>Controlling these emotions, rather than being controlled by them, is the key to transforming every setback into a stepping stone towards success.</p>
<p>In a world where the only constant is change, adaptability becomes your strongest weapon. As creators, it's crucial to align your perception as closely as possible with reality, undistorted by fallacies or emotional biases. This alignment helps in making decisions that are rooted in facts and data, rather than ego or fleeting emotions. </p>
<p>The toughest battles often lie within, and winning this internal struggle sets the foundation for external victories. Here are some strategies to help you learn from your setbacks.</p>
<h3 id="heading-create-a-failure-analysis-system">Create a Failure Analysis System</h3>
<p>Establish a structured approach to analyze each failure. This system should include identifying the cause of the failure, its impact, and lessons learned. Reflect on what went wrong, what was done well, and how you would approach the situation differently next time.</p>
<p><strong>Example</strong>: Suppose a software developer's new feature causes a system crash. The failure analysis could involve examining the coding changes, understanding how they interacted with the existing system, and reviewing test procedures. </p>
<p>In this case, you can maintain a 'Failure Log' where each incident is recorded with details about what happened, why it happened, and how it was resolved. Regularly review this log for patterns and areas of improvement.</p>
<h3 id="heading-establish-a-feedback-loop-and-be-open-to-constructive-criticism">Establish a Feedback Loop and Be Open to Constructive Criticism</h3>
<p>Implement a regular feedback mechanism. This could be daily, weekly, or monthly, and involve different techniques to ensure the feedback is accurate and constructive. Use KPIs (Key Performance Indicators) to track progress and adjust strategies accordingly.</p>
<p>You should also actively seek out and be open to constructive criticism. This feedback can provide insights you might not have considered and help you avoid similar mistakes in the future.</p>
<p><strong>Example</strong>: A graphic designer could request feedback from colleagues on a new design project using a structured survey or informal meetings. Set up regular review sessions with peers or supervisors to discuss your work. Utilize tools like 360-degree feedback for a comprehensive view.</p>
<h3 id="heading-have-a-personal-reflection-routine">Have a Personal Reflection Routine</h3>
<p>Dedicate time for self-reflection, such as journaling, meditation, or other introspective practices. This habit can help you understand your responses to failures and devise strategies for improvement.</p>
<p><strong>Example</strong>: End each day by writing in a journal about what went well, what didn't, and what could be improved. Use techniques like meditation or mindfulness to reflect on your reactions to successes and failures, understanding your triggers and responses.</p>
<h3 id="heading-build-resilience-and-mental-fitness">Build Resilience and Mental Fitness</h3>
<p>Engage in activities that build resilience, like mindfulness exercises, regular physical activity, or consuming inspirational content. Resilience is key to bouncing back from failures.</p>
<p>Make sure you do things that help keep your mind and spirit sharp. This could include spiritual practices, intellectual hobbies, or continual learning. A strong mind and spirit are crucial for overcoming challenges.</p>
<p><strong>Example</strong>: Engage in regular physical activities like jogging or yoga, which are known to improve mental health. Incorporate practices like deep breathing or guided meditations into your daily routine to strengthen mental resilience.</p>
<h3 id="heading-develop-a-focused-approach">Develop a Focused Approach</h3>
<p>Avoid spreading yourself too thin across multiple projects. Concentrate on excelling in one area before expanding your focus. This targeted approach can prevent overextension and increase the likelihood of success.</p>
<p><strong>Example</strong>: If you're a multi-skilled professional, prioritize projects that align most closely with your career goals rather than trying to tackle everything. Regularly evaluate your workload and refocus on tasks that contribute most to your primary objectives.</p>
<h3 id="heading-seek-mentorship-and-guidance">Seek Mentorship and Guidance</h3>
<p>Actively seek mentors who can provide wisdom, advice, and learnings from their experiences. Regular interactions with mentors can provide invaluable insights and guidance.</p>
<p><strong>Example</strong>: Find a mentor in your field who has a career trajectory you admire. Set up regular meetings to discuss your progress and challenges. Utilize networking events or platforms like LinkedIn to connect with potential mentors.</p>
<h3 id="heading-engage-in-data-driven-decision-making">Engage in Data-Driven Decision Making</h3>
<p>Base your decisions on factual data and analysis rather than emotions or assumptions. Use market research, historical data, and trends to inform your choices.</p>
<p><strong>Example</strong>: Before launching a marketing campaign, analyze previous campaigns' data to guide your strategies. Use analytical tools to gather data and make informed decisions based on that data.</p>
<h3 id="heading-perform-thorough-due-diligence">Perform Thorough Due Diligence</h3>
<p>Before making significant decisions, conduct comprehensive research to understand all aspects and potential risks. This approach helps in making informed and less risky decisions.</p>
<p><strong>Example</strong>: Before investing in new technology, research its compatibility with current systems and potential ROI. Create a checklist of key criteria that must be met before proceeding with major decisions.</p>
<h3 id="heading-fail-fast-and-learn-quickly">Fail Fast and Learn Quickly</h3>
<p>Embrace the concept of failing fast to learn quickly. Use each failure as a stepping stone to gain insights, refine strategies, and innovate.</p>
<p>Also, try to stay adaptable and flexible in your approach. The ability to pivot and adjust strategies in response to failures is key to long-term success.</p>
<p><strong>Example</strong>: If a new product feature isn't resonating with users, quickly pivot to alternative solutions based on user feedback. Adopt an agile methodology, allowing for rapid iteration and adaptation based on feedback.</p>
<h3 id="heading-let-go-of-the-past-and-dont-dwell-on-regrets">Let Go of the Past and Don't Dwell on Regrets</h3>
<p>Avoid dwelling on past failures or successes. Acknowledge them, learn from them, and then focus on the present and future.</p>
<p>Understand that dwelling on past mistakes or missed opportunities is counterproductive. Instead, use these experiences as lessons to shape a better future.</p>
<p>Keep your focus on the current situation and future goals. While the past can provide valuable lessons, it should not overshadow your present actions or future plans. And try to cultivate the ability to emotionally detach from past failures. Learn to view setbacks objectively and as opportunities for growth.</p>
<p><strong>Example</strong>: If a past project failed, instead of ruminating, focus on the lessons learned and how they can be applied in future projects. Practice mindfulness to stay present-focused and learn from the past without dwelling on it.</p>
<h3 id="heading-continuously-improve">Continuously Improve</h3>
<p>Commit to a mindset of continuous improvement. Even if it's just a little bit at a time. Always look for ways to enhance your skills, knowledge, and strategies.</p>
<p><strong>Example</strong>: Regularly update your skills, whether through online courses, workshops, or self-study. Set aside time each week for personal development and learning.</p>
<h3 id="heading-balance-emotions-and-facts">Balance Emotions and Facts</h3>
<p>Strive to balance emotional responses with factual analysis. Emotional intelligence is critical in understanding and learning from failures.</p>
<p><strong>Example</strong>: If you're feeling overwhelmed by a project, step back to objectively analyze the situation before reacting. Break it down into smaller, more manageable chunks. Develop emotional intelligence skills through training and practice.</p>
<h3 id="heading-embrace-change-and-uncertainty">Embrace Change and Uncertainty</h3>
<p>Develop comfort with change and uncertainty. The ability to navigate and adapt to changing circumstances is crucial in today’s dynamic environment.</p>
<p><strong>Example</strong>: If your industry is undergoing a shift (for example, digital transformation), embrace the change by upskilling or reskilling. Stay informed about industry trends and be flexible in adapting your skills and strategies.</p>
<h3 id="heading-create-a-supportive-network">Create a Supportive Network</h3>
<p>Build a network of colleagues, peers, and mentors who can offer support, advice, and different perspectives. A strong support system can be invaluable during challenging times.</p>
<p><strong>Example</strong>: Join professional groups or forums in your field where you can share experiences and gain insights. Actively engage in networking, both online and offline, to build a support system of peers and mentors.</p>
<p>The journey of a creator is a complex tapestry woven with successes and failures. Embracing this duality with a strategic approach, resilience, and a fact-based mindset is crucial. </p>
<p>Each failure is an opportunity to learn, grow, and come back stronger. By systematically analyzing setbacks, maintaining focus, building resilience, and making data-driven decisions, creators can ensure that their failures are not dead-ends but detours leading to greater success. </p>
<p>Let the past be a teacher, not a jailer. Look forward, act with confidence, and shape a future that echoes with the triumphs born from the ashes of past failures.</p>
<h2 id="heading-14-handling-change-how-to-navigate-and-conquer-the-unpredictable">14. Handling Change: How to Navigate and Conquer the Unpredictable</h2>
<p>As creators, we dwell in an era where rigidity is a fast track to obsolescence. Embracing flexibility is not just a choice – it's a necessity. </p>
<p>This dynamic landscape, especially in the age of AI, demands an agile and fluid approach. While large corporations grapple with their inherent rigidity, creators like you possess a unique advantage – the ability to pivot swiftly and respond creatively to the ever-changing demands of the market.</p>
<p>This chapter is about harnessing that inherent flexibility, turning the unpredictability of our times into your greatest asset. Here, you'll discover how to channel the chaotic energy of change into innovative products and solutions that resonate with the needs of today and tomorrow. </p>
<p>In this world of constant flux, your agility as a creator isn't just a skill – it's your superpower. Let's dive into mastering this art, transforming challenges into opportunities, and thriving amidst the whirlwind of change.</p>
<h3 id="heading-embrace-fluidity-and-adaptability">Embrace Fluidity and Adaptability</h3>
<p>In a world where change is the only constant, embracing fluidity and adaptability becomes crucial for survival and success in any field. Being adaptable means having the ability to quickly adjust to new conditions and challenges without losing your core purpose. It's about being responsive to changes in the market, technology, and consumer behavior.</p>
<p>Fluidity implies a seamless transition from one state or strategy to another, often requiring a break from traditional methods or thinking patterns. It involves a mindset that is open to new ideas, flexible in approach, and innovative in finding solutions.</p>
<p>Embracing these qualities allows you and  your businesses to remain competitive and relevant in an ever-evolving landscape. This dynamic approach ensures that you can pivot strategies as needed, capitalize on emerging opportunities, and mitigate risks associated with change.</p>
<p>Here are some tips to help you remain fluid and adaptable:</p>
<ul>
<li><strong>Stay informed</strong>: Regularly update yourself on industry trends and shifts to anticipate change effectively.</li>
<li><strong>Flexible strategies</strong>: Create adaptable business plans and strategies that can easily pivot in response to market changes.</li>
<li><strong>Embrace technology</strong>: Utilize AI, machine learning, and other tech innovations proactively, not just reactively.</li>
<li><strong>Responsive design thinking</strong>: Incorporate design thinking principles to develop solutions that are adaptable to changing user needs.</li>
<li><strong>Scenario planning</strong>: Engage in scenario planning exercises to prepare for various future possibilities and challenges.</li>
<li><strong>Cultivate an adaptive culture</strong>: Encourage a workplace culture that values flexibility, quick learning, and innovative thinking.</li>
</ul>
<p>When Satya Nadella took over as CEO in 2014, Microsoft was perceived as lagging behind in the rapidly evolving tech industry. Nadella's first move was to shift the company culture from “know-it-all” to “learn-it-all,” fostering a mindset of continuous learning and adaptability. </p>
<p>He recognized the potential of cloud computing and AI as future technological pillars and reoriented Microsoft's focus towards these areas. This strategic pivot not only rejuvenated Microsoft but also positioned it as a leader in cloud services with Azure, and AI applications. </p>
<p>Nadella’s leadership exemplifies how adaptability to market trends and internal culture change can rejuvenate an established company.</p>
<h3 id="heading-build-your-resilience-muscle">Build Your Resilience Muscle</h3>
<p>This is a good time to review what it takes to become resilient. Building resilience is like training a muscle, requiring consistent effort and the right mindset. It's about developing the mental fortitude to withstand and bounce back from adversity, whether in personal life or professional settings. </p>
<p>Resilience involves maintaining a balance in your life, managing stress effectively, and viewing challenges as opportunities to grow. It requires a deep understanding of your own strengths and weaknesses, allowing you to adapt your strategies accordingly. </p>
<p>Resilient people are known for their perseverance, ability to maintain a positive outlook in the face of difficulties, and the capacity to recover from setbacks stronger than before. They also understand the importance of seeking support when needed, recognizing that resilience is not about going it alone but about knowing when and how to leverage resources and networks. </p>
<p>Building resilience is essential for long-term success and well-being, as it equips you with the tools to navigate life's inevitable ups and downs.</p>
<ul>
<li><strong>Mindset of perseverance</strong>: Cultivate a mindset that views challenges as opportunities to learn and grow.</li>
<li><strong>Self-care routine</strong>: Establish routines that prioritize physical and mental well-being, such as regular exercise, meditation, and healthy eating.</li>
<li><strong>Community support</strong>: Engage with supportive networks, either professionally or personally, for shared learning and encouragement.</li>
<li><strong>Emotional intelligence development</strong>: Focus on developing emotional intelligence to manage stress and recover from setbacks.</li>
<li><strong>Resilience training</strong>: Participate in resilience training programs or workshops to build coping strategies.</li>
<li><strong>Positive affirmations</strong>: Use positive affirmations and self-talk to reinforce resilience.</li>
<li><strong>Reflective practices</strong>: Regularly engage in reflective practices like journaling to process experiences and build resilience.</li>
</ul>
<p>Oprah Winfrey's path to becoming a global media leader was fraught with personal and professional obstacles, including poverty, abuse, and discrimination. Her resilience is evident in how she transformed these hardships into a narrative of empowerment, both for herself and her audience. </p>
<p>Winfrey's focus on self-care, mental health, and maintaining a balanced life despite her demanding career is a testament to her resilient nature. Her ability to bounce back from adversity and continue to innovate in the media industry sets a powerful example of how resilience can drive long-term success and personal fulfillment.</p>
<h3 id="heading-develop-a-change-ready-mindset">Develop a Change-Ready Mindset‌‌</h3>
<p>A change-ready mindset is key to thriving in today's fast-paced world. It involves being prepared and eager to embrace changes, whether expected or unexpected. </p>
<p>This mindset is characterized by a willingness to let go of old habits and approaches, and the ability to quickly adapt to new information or circumstances. It's about seeing change not as a threat, but as an opportunity for growth and innovation. </p>
<p>Developing a change-ready mindset requires an openness to learning and an acceptance that change is an integral part of growth, both personally and professionally. It involves a proactive approach to seeking out new experiences and being willing to take calculated risks. </p>
<p>This mindset is crucial for success in an era where technological advancements and global dynamics can swiftly alter the landscape in which we operate. By fostering a change-ready mindset, you and your organization can position yourselves to capitalize on new opportunities and navigate challenges with agility and confidence.</p>
<p>So how do you cultivate a change-ready mindset? Here are some tips:</p>
<ul>
<li><strong>Growth focus</strong>: Embrace a lifelong learning approach, viewing every experience as an opportunity to grow.</li>
<li><strong>Positive reinforcement</strong>: Regularly remind yourself of past adaptability and learning experiences to build confidence.</li>
<li><strong>Embrace new experiences</strong>: Actively seek out and engage in new experiences to enhance adaptability and resilience.</li>
<li><strong>Encourage curiosity</strong>: Cultivate a culture of curiosity and open-mindedness in your professional and personal life.</li>
<li><strong>Challenge comfort zones</strong>: Regularly step out of comfort zones to test and expand your adaptability limits.</li>
<li><strong>Feedback reception</strong>: Actively seek and constructively use feedback to adjust and improve.</li>
<li><strong>Mentorship and coaching</strong>: Engage in mentorship or coaching to develop and maintain relationships.</li>
</ul>
<p>Reed Hastings' approach to Netflix's evolution is a textbook case of a change-ready mindset. In the early 2000s, despite the success of their DVD rental model, Hastings foresaw the potential of online streaming. This foresight led to the risky yet ultimately successful transition of Netflix into a streaming service. </p>
<p>His readiness to embrace change and disrupt Netflix’s own business model before others could, highlights the importance of being proactive and adaptable in the face of industry evolution. Hastings’ story illustrates how a change-ready mindset can turn potential threats into groundbreaking opportunities.</p>
<h3 id="heading-anticipate-and-plan-for-change">Anticipate and Plan for Change</h3>
<p>Anticipating and planning for change involves a proactive approach to identifying and preparing for potential future shifts. This strategy is rooted in understanding that change is inevitable and often unpredictable. By staying ahead of trends, conducting thorough market analysis, and regularly engaging in scenario planning, people and businesses can better prepare for various outcomes. </p>
<p>This proactive stance allows for quicker adaptation when change does occur, minimizing disruption and maximizing opportunities. </p>
<p>Anticipating change involves not just looking at current trends but also projecting future possibilities, considering various scenarios, and preparing contingency plans. It’s about being one step ahead, so when change occurs, you’re ready with strategies and solutions, rather than reacting in the moment.</p>
<ul>
<li><strong>Predictive analysis</strong>: Regularly utilize tools like market research, customer feedback, and trend analysis to anticipate shifts.</li>
<li><strong>Scenario planning</strong>: Engage in scenario planning exercises to envision and prepare for a range of possible futures.</li>
<li><strong>Continuous learning</strong>: Dedicate yourself to lifelong learning, ensuring your skills and knowledge remain relevant amidst change.</li>
<li><strong>Regular industry reviews</strong>: Stay informed about industry developments and emerging technologies to foresee potential disruptions.</li>
<li><strong>Feedback mechanisms</strong>: Implement systems to gather and analyze feedback from customers and stakeholders to anticipate their evolving needs.</li>
<li><strong>Risk assessment and management</strong>: Regularly conduct risk assessments to identify potential changes and develop strategies to manage them.</li>
<li><strong>Proactive innovation</strong>: Encourage innovation within your team or organization to stay ahead of potential changes.</li>
</ul>
<p>Jeff Bezos, the founder of Amazon, exemplifies keen foresight in business strategy. Initially starting as an online bookstore, Bezos rapidly expanded Amazon into a diverse e-commerce platform, anticipating the exponential growth of online shopping. </p>
<p>His vision didn’t stop there. Bezos foresaw the potential of cloud computing before it became mainstream. This led to the creation of Amazon Web Services (AWS), now a dominant player in the cloud services sector.   </p>
<p>Bezos's approach to business involves constantly looking forward to the next big trend or need. He invests in long-term projects, like space exploration through Blue Origin, aligning with his belief in the necessity of anticipating future societal and technological shifts. Bezos's career is an example of how anticipating and preparing for change can lead to pioneering innovations and market dominance.</p>
<h3 id="heading-clear-and-effective-communication">Clear and Effective Communication</h3>
<p>Clear and effective communication is vital, especially during times of change. It involves articulating messages in a way that is easily understood and resonates with your audience. </p>
<p>This skill is crucial for conveying the reasons behind changes, the benefits they bring, and the actions required from stakeholders. Effective communication helps in aligning everyone’s understanding and expectations, which reduces resistance and fosters a smoother transition. </p>
<p>It also involves active listening, ensuring that feedback and concerns are heard and addressed. In a business context, this could mean transparently sharing information about company changes, listening to employee concerns, and providing regular updates. </p>
<p>Clear and effective communication builds trust, reduces uncertainty, and is essential for successful navigation through change.</p>
<ul>
<li><strong>Transparency in communication</strong>: Be transparent in your communications, especially during times of change.</li>
<li><strong>Feedback loops</strong>: Create and maintain effective feedback mechanisms to understand the impact of your communications and refine as needed.</li>
<li><strong>Active listening</strong>: Practice active listening to understand concerns and perspectives of others during times of change.</li>
<li><strong>Regular updates</strong>: Keep stakeholders informed with regular updates about changes and progress.</li>
<li><strong>Tailored messaging</strong>: Tailor your communication style and content to your audience for maximum clarity and impact.</li>
<li><strong>Training in communication skills</strong>: Invest in training to enhance communication skills across your team or organization.</li>
<li><strong>Effective use of channels</strong>: Utilize appropriate channels for different types of communications to ensure messages are received and understood.</li>
</ul>
<p>Sheryl Sandberg’s role in steering Facebook through various controversies highlights her skill in clear and effective communication. She has been pivotal in articulating Facebook's policies and responses to privacy concerns and misinformation, often addressing complex issues with clarity and empathy.</p>
<p>Sandberg's communication style is not just about conveying information but also about building relationships and trust with stakeholders. Her ability to communicate effectively under pressure demonstrates how clear communication can guide a company through challenges and maintain its reputation.</p>
<h3 id="heading-set-clear-and-achievable-goals">Set Clear and Achievable Goals</h3>
<p>‌‌Setting clear and achievable goals is a fundamental step in navigating through change effectively. Goals provide direction and purpose, serving as beacons during times of uncertainty. By defining what you aim to achieve, goals help maintain focus, drive motivation, and give a sense of accomplishment upon completion. </p>
<p>In the context of change, goals need to be adaptable, allowing for shifts in strategies as circumstances evolve. Setting SMART (Specific, Measurable, Achievable, Relevant, Time-bound) goals ensures that objectives are well-defined and realistic, increasing the likelihood of success. </p>
<p>Regularly reviewing and adjusting goals in response to changing environments ensures they remain relevant and attainable.</p>
<ul>
<li><strong>SMART goal setting</strong>: Adopt the SMART framework for setting goals that are specific, measurable, achievable, relevant, and time-bound.</li>
<li><strong>Regular goal reviews</strong>: Schedule regular reviews of your goals to assess progress and make necessary adjustments.</li>
<li><strong>Actionable steps</strong>: Break down each goal into smaller, manageable tasks to avoid feeling overwhelmed and ensure steady progress.</li>
<li><strong>Align goals with change</strong>: Ensure that your goals align with the nature and direction of change.</li>
<li><strong>Visual goal reminders</strong>: Use visual aids like goal boards or digital reminders to keep your goals in constant sight.</li>
<li><strong>Celebrate milestones</strong>: Acknowledge and celebrate reaching milestones towards your larger goals to maintain motivation.</li>
<li><strong>Seek feedback on goals</strong>: Regularly seek feedback from mentors or peers on your goals to ensure they are realistic and aligned with change dynamics.</li>
</ul>
<p>Tim Cook, succeeding Steve Jobs as Apple’s CEO, faced the enormous challenge of continuing Apple's legacy of innovation. Cook's strategy focused on clear, achievable goals: expanding Apple’s product ecosystem, entering new markets like China, and launching new products like the Apple Watch and AirPods. </p>
<p>His focus on diversifying Apple's revenue sources, particularly through services, has been crucial for the company's sustained growth. Cook’s tenure shows how setting and pursuing well-defined, realistic goals can lead to significant achievements and the continuation of a company’s pioneering legacy.</p>
<p>The key to success in this landscape is adaptability. Embrace change as an opportunity, not a challenge. Stay informed, flexible, and ready to incorporate new technologies into your strategy. Building resilience is crucial – it's about viewing setbacks as learning opportunities and maintaining a strong support network.</p>
<p>Developing a mindset ready for change involves seeing each challenge as a chance for growth. Anticipate future shifts with predictive analysis and scenario planning, and communicate your vision clearly to your audience. Set SMART goals to provide clear direction through change and break these down into manageable steps.</p>
<p>Collaboration is vital. Diverse perspectives lead to richer solutions. In our digital age, leveraging technology and innovation is a must. Learn from past experiences and continuously adapt your strategy for future success.</p>
<h2 id="heading-15-health-hack-how-to-fuel-your-ambition-with-wellness">15. Health Hack: How to Fuel Your Ambition with Wellness</h2>
<p>In the world of creation and innovation, your health is as pivotal as your ideas. It's the fuel that powers your ambition. </p>
<p>As creators, you often juggle the demands of your work, sometimes at the expense of your well-being. But remember, without a solid foundation of health, even the most brilliant ideas won't matter. </p>
<p>In this chapter, we'll dive into practical and effective health hacks designed to keep you at the top of your game. These strategies are not just about avoiding burnout – they're about optimizing your physical and mental energy to enhance your creative output.</p>
<h3 id="heading-optimal-nutrition-for-energy">Optimal Nutrition for Energy</h3>
<p>The right nutrition fuels not only the body but also the mind. Incorporating a balanced diet rich in vitamins, minerals, and essential nutrients is fundamental for sustained energy and focus. </p>
<p>Focus on whole foods, including fruits, vegetables, lean proteins, and whole grains. Avoid processed foods and excessive sugar, which can lead to energy crashes. Small, frequent meals can help maintain steady energy levels throughout the day.</p>
<h3 id="heading-mindset-for-success">Mindset for Success</h3>
<p>A positive mindset is a catalyst for success. Cultivate resilience and mental agility to overcome challenges and setbacks. </p>
<p>Practice positive self-talk and affirmations to boost confidence and maintain motivation. Surround yourself with positive influences and inspirational content. </p>
<p>Remember, a healthy mindset is nurtured by a combination of self-awareness, continuous learning, and an optimistic outlook on life and challenges.</p>
<h3 id="heading-revitalizing-sleep-patterns">Revitalizing Sleep Patterns</h3>
<p>Quality sleep is non-negotiable for peak performance. Establish a regular sleep routine, aiming for 7-9 hours per night. </p>
<p>Create a sleep-conducive environment – dark, quiet, and cool – and invest in a comfortable mattress and pillows. Limit screen time before bed to improve sleep quality. If you struggle with sleep, consider relaxation techniques like meditation or reading before bed to unwind.</p>
<h3 id="heading-exercise-for-mental-clarity">Exercise for Mental Clarity</h3>
<p>Regular physical activity is essential for mental clarity and creativity. Choose an exercise regimen that you enjoy, be it yoga, running, or weight training. </p>
<p>Aim for at least 30 minutes of exercise daily. Exercise not only improves physical health but also reduces stress and enhances cognitive function. </p>
<p>The best exercise is the one you'll consistently do – so find something that fits your lifestyle and preferences.</p>
<h3 id="heading-stress-management-techniques">Stress Management Techniques</h3>
<p>Effectively managing stress is key to maintaining a creative and productive mindset. Develop a toolkit of stress-relief techniques such as deep breathing, meditation, or mindfulness practices. </p>
<p>Regularly engage in activities that relax and rejuvenate you, like hobbies or spending time in nature. Learn to recognize early signs of stress and take proactive steps to manage it.</p>
<h3 id="heading-dietary-adjustments-for-wellness">Dietary Adjustments for Wellness</h3>
<p>Simple dietary adjustments can significantly enhance your health and energy levels. </p>
<p>Incorporate more plant-based foods into your diet for their high nutrient content. Reduce intake of processed and high-sugar foods. Experiment with meal timings and sizes to find what works best for your body. Stay hydrated throughout the day, as even mild dehydration can affect mood and energy levels.</p>
<h3 id="heading-mindfulness-and-meditation">Mindfulness and Meditation</h3>
<p>Integrating mindfulness and meditation into your daily routine can significantly enhance focus and reduce anxiety. </p>
<p>Start with short, daily sessions and gradually increase the duration. Use apps or guided sessions if you're a beginner. Practice being present in the moment during everyday activities. </p>
<p>Mindfulness can increase your emotional resilience and improve your response to stress.</p>
<h3 id="heading-time-management-for-balance">Time Management for Balance</h3>
<p>Effective time management leads to a more balanced life. Prioritize tasks based on importance and urgency. Use tools like calendars and to-do lists to organize your schedule. Learn to delegate and say no to non-essential tasks. Set aside time for rest and hobbies – balance is key to long-term productivity and creativity. Remember, being busy doesn’t always mean being productive.</p>
<h3 id="heading-building-a-supportive-network">Building a Supportive Network</h3>
<p>Cultivate a network of supportive peers, mentors, and friends. Engage with communities that share your interests and values. Seek feedback and advice when faced with challenges. Offer your support to others, as helping can be a source of personal satisfaction and growth. </p>
<p>Remember, the quality of your network often influences your personal and professional growth.</p>
<p>This chapter has provided you with an arsenal of health tips, each designed to enhance your physical and mental energy, thus amplifying your creative prowess. The journey of a creator is not just about producing remarkable work – it's equally about nurturing the mind and body that make such work possible.</p>
<p>By embracing these strategies, you're not just avoiding the pitfalls of burnout. You're also actively investing in a lifestyle that bolsters your health and, in turn, your ability to innovate and create. </p>
<p>From optimal nutrition and a resilient mindset to revitalizing sleep and effective stress management, each element plays a pivotal role in maintaining your peak performance. The integration of mindfulness, balanced time management, and a supportive network further solidifies your foundation, enabling you to thrive in both your personal and professional endeavors.</p>
<p>Remember, your health is not a separate entity from your creative ambitions. Rather, it's the very foundation that sustains and propels them. </p>
<p>As you continue to push the boundaries of innovation and creativity, let these health hacks be your guide, ensuring that you remain vibrant, focused, and ready to conquer whatever challenges lie ahead. Your greatest creations await, and they start with a commitment to your own health and wellness.</p>
<h2 id="heading-16-fueled-by-passion-how-to-find-purpose-in-what-you-love">16. Fueled by Passion: How to Find Purpose in What You Love</h2>
<p>"Follow your passion" is a phrase often dispensed as life-changing advice, but its simplicity masks a complex reality. This well-intentioned counsel, frequently misunderstood and misapplied, fails to acknowledge the depth of what truly drives us. </p>
<p>Passion, a potent and sometimes uncontrollable emotion, propels us towards specific activities, interests, or objectives. But this understanding of passion oversimplifies the intricate process of finding and cultivating a deep, enduring commitment to a pursuit.</p>
<p>At the heart of this journey is the concept of the 'flow state' – a condition of complete absorption in an activity, where time seems to stand still, and a sense of satisfaction is profoundly felt. </p>
<p>Many associate this state with the essence of passion, where enjoyment and engagement reach their peak. But the ability to regularly achieve this state isn't merely a matter of chance. It requires development, practice, and a disciplined approach to mastering a skill or area of interest.</p>
<p>Overcoming the barrier to reach a state where discipline outweighs mere motivation is pivotal. It's at this juncture that you can often find true passion – not in the fleeting throes of excitement, but in the steady glow of commitment and skill enhancement. </p>
<p>This chapter delves into the heart of what it means to cultivate a passion. We'll explore the craftsman mindset, which prioritizes skill and value production over fleeting enthusiasm. </p>
<p>For creators, this mindset is crucial. It's about refining one's craft to the point of indispensability and finding fulfillment in the process of creation, rather than the pursuit of a nebulous concept of passion. </p>
<p>By redefining passion through the lens of discipline, skill development, and value creation, we can uncover a more sustainable and fulfilling path to personal and professional fulfillment.</p>
<h3 id="heading-dont-follow-your-passion">Don’t Follow Your Passion</h3>
<p>The Passion Hypothesis, which suggests that occupational happiness comes from finding a job that matches your passion, is a pervasive myth. Notable figures like Steve Jobs, who is often associated with the "follow your passions" mantra, didn't start with a passion for computers. Instead, he saw it as an opportunity to earn quick cash. </p>
<p>His love for Apple computers developed over time, not as a result of an initial passion. And career passions are rare. Most passions, such as reading, can't often be directly translated into a career. </p>
<p>For creators, this means that simply being passionate about creating may not be enough to build a fulfilling career. Instead, it's crucial to focus on developing valuable skills and adopting a craftsman mindset.</p>
<h3 id="heading-be-so-good-they-cant-ignore-you-or-the-importance-of-skills">Be So Good They Can’t Ignore You (Or, the importance of skills)</h3>
<p>The craftsman mindset emphasizes the value you're producing in your job, rather than what value your job offers you. This mindset can be particularly beneficial for creators, as it encourages continuous improvement and a focus on the quality of the work they produce.</p>
<p>Adopting the craftsman mindset can help creators avoid the pitfalls of the passion mindset, which can lead to dissatisfaction and confusion. </p>
<p>The passion mindset often results in a hyper-awareness of what you don't like about your job and constant questioning of whether it's the right fit. This can lead to irrational decisions, such as jumping into a field where you lack skills but believe you have passion, like yoga for instance.</p>
<p>In contrast, the craftsman mindset encourages creators to approach their work as a true performer, striving to improve the quality of what they produce. The goal is to become so good that they can't be ignored, regardless of what they do for a living. This mindset can lead to the development of rare and valuable skills, also known as career capital.</p>
<h3 id="heading-build-career-capital">Build Career Capital</h3>
<p>Career capital is the collection of skills, experiences, and abilities that you have that are both rare and valuable. For creators, this could include technical skills, unique artistic perspectives, or a deep understanding of a particular medium or audience. </p>
<p>Building career capital is a crucial step towards finding a great job, one that is rich with creativity, impact, and control. The more career capital you acquire, the more opportunities will come your way. This is because when you have developed skills that are too valuable to be ignored, you get to choose a great job.</p>
<p>But it's also important to know when to leave a job. If a job presents few opportunities to distinguish yourself by developing relevant skills, focuses on something you think is useless or actively bad for the world, or forces you to work with people you really don't like, then it might be time to consider leaving.</p>
<h3 id="heading-the-creators-journey">The Creator's Journey</h3>
<p>For creators, the journey towards occupational happiness often involves a delicate balance of passion and pragmatism. While passion can provide the initial spark and ongoing motivation, it's the craftsman mindset and the relentless pursuit of skill development that can turn that passion into a viable career.</p>
<p>By focusing on what value they're producing, creators can continuously improve their work, build their career capital, and ultimately find purpose in what they love. This approach can lead to a fulfilling career that is not just about following a passion, but also about becoming so good that they can't be ignored.</p>
<h3 id="heading-turn-work-into-play">Turn Work into Play</h3>
<p>The concept of turning work into play is about finding enjoyment in the tasks you do, even if they seem mundane or repetitive. This can be achieved by setting clear and actionable goals, immersing yourself in the activity, and constantly seeking ways to optimize your performance. </p>
<p>This approach can transform almost certain boredom into full engagement and flow, a state of consciousness where you're fully absorbed in what you're doing and everything is in alignment. </p>
<p>For creators, this could mean setting specific goals for each project, constantly seeking ways to improve your craft, and finding joy in the process of creation itself. This approach can help you stay motivated and engaged, even when you're working on challenging or repetitive tasks.</p>
<h3 id="heading-cultivate-an-autotelic-personality">Cultivate an Autotelic Personality</h3>
<p>An autotelic personality is one that is intrinsically motivated, curious, and not overly self-centered. People with this type of personality often do things for the sheer satisfaction of doing them, rather than for any external reward. They are self-driven, non-materialistic, and don't require much in the way of comfort. They have the ability to transform regular, ordinary experiences into optimal experiences of flow.</p>
<p>For creators, cultivating an autotelic personality can mean focusing on the joy of creation itself, rather than external rewards like money or fame. It can also mean being curious and open-minded, constantly seeking new ideas and ways to improve your craft. </p>
<p>This approach can help you stay motivated and engaged in your work, even when you're facing challenges or setbacks.</p>
<p>So while passion can be a powerful motivator, it's not the only factor that can lead to occupational happiness. By adopting a craftsman mindset, turning work into play, and cultivating an autotelic personality, creators can find purpose and fulfillment in their work, regardless of whether it aligns with their initial passions.</p>
<h2 id="heading-17-laser-focus-how-to-harness-the-power-of-concentration">17. Laser Focus: How to Harness the Power of Concentration</h2>
<p>In the whirlwind of our modern lives, mastering the art of concentration is a necessary skill. As we navigate through the complexities of a technology-driven society, our ability to focus deeply on a single task has become more valuable than ever. </p>
<p>This chapter delves into the transformative power of laser focus, offering practical and actionable advice to harness this ability. This can enhance both the personal and professional spheres of our lives.</p>
<h3 id="heading-the-essence-of-concentration">The Essence of Concentration</h3>
<p>Concentration, in its purest form, is the ability to direct your mental energy towards a specific task, undeterred by distractions or competing priorities. It's the mental muscle behind every success story, an invisible force that empowers us to tackle challenges with precision and effectiveness. </p>
<p>But in a world brimming with distractions, maintaining this focus can feel like an uphill battle.</p>
<p>To develop a laser-sharp focus, you'll need to begin with cultivating the right mindset. This involves understanding the value of concentration and its impact on your overall performance. Recognize that every moment of focused effort is a step towards achieving your goals, and that distractions, no matter how trivial, chip away at this progress.</p>
<h3 id="heading-strategies-for-enhanced-concentration">Strategies for Enhanced Concentration</h3>
<ol>
<li><strong>Set clear goals</strong>: Begin by defining what you wish to achieve in precise terms. Clear goals act as beacons, guiding your focus amidst chaos.</li>
<li><strong>Create a distraction-free environment</strong>: Tailor your workspace to minimize distractions. This might involve physical changes like a clutter-free desk or digital measures such as using apps that block social media during work hours.</li>
<li><strong>Time management</strong>: Allocate specific time slots for focused work. The <a target="_blank" href="https://www.freecodecamp.org/news/how-to-quantify-and-visualize-learning-with-the-pomodoro-technique/">Pomodoro technique</a>, which I mentioned earlier, is an effective method to maintain high levels of concentration.</li>
<li><strong>Mindfulness and meditation</strong>: Practices like mindfulness and meditation enhance your ability to control your attention. Regular practice can significantly improve your concentration levels.</li>
<li><strong>Regular breaks</strong>: The human brain can only focus effectively for a certain period. Regular breaks are not just restful pauses but essential components of sustained concentration.</li>
</ol>
<h3 id="heading-how-to-overcome-barriers-to-focus">How to Overcome Barriers to Focus</h3>
<p>Overcoming barriers to focus demands a comprehensive strategy that addresses both internal and external challenges. </p>
<p>Understanding these barriers is the first step to developing effective solutions. By recognizing and actively managing these obstacles, you can significantly enhance your concentration and productivity.</p>
<h4 id="heading-internal-barriers">Internal Barriers:</h4>
<ol>
<li><strong>Mental fatigue</strong>: Mental exhaustion is a significant barrier to concentration. Combat this by ensuring adequate sleep, balanced nutrition, and incorporating relaxation techniques into your routine. Mindful practices like yoga and meditation can rejuvenate your mind.</li>
<li><strong>Lack of motivation</strong>: To address this, set small, achievable goals. The satisfaction of completing these goals can boost your motivation. Also try to connect your tasks to a larger, meaningful objective, making the work more engaging and purpose-driven.</li>
<li><strong>Emotional distractions</strong>: Emotional turbulence can hinder concentration. Practice emotional regulation techniques such as journaling or speaking with a trusted confidant. Developing emotional intelligence helps in managing these distractions effectively.</li>
</ol>
<h4 id="heading-external-barriers">External Barriers:</h4>
<ol>
<li><strong>Environmental distractions</strong>: Identify factors in your environment that disrupt focus. It could be noise, clutter, or interruptions. Address these by creating a dedicated workspace, using noise-cancelling headphones, or setting boundaries with those around you.</li>
<li><strong>Technology interruptions</strong>: Constant notifications and the allure of social media can break your concentration. Use technology mindfully by turning off unnecessary notifications and allotting specific times to check emails or social media.</li>
</ol>
<h3 id="heading-build-a-routine">Build a Routine</h3>
<p>Establishing a routine that fosters deep concentration involves several steps:</p>
<ol>
<li><strong>Structured schedule</strong>: Plan your day with specific blocks dedicated to focused work. Adhere to these times as non-negotiable periods of deep work.</li>
<li><strong>Balanced work-break ratio</strong>: Incorporate the concept of work-break cycles. Techniques like the Pomodoro Technique can be highly effective, balancing intense focus with short breaks.</li>
<li><strong>Preparation rituals</strong>: Start your focus sessions with a ritual. It could be a few minutes of meditation, organizing your workspace, or a cup of tea. Rituals signal your brain to transition into a state of concentration.</li>
<li><strong>Reflection and adjustment</strong>: End each day with a brief reflection on what worked and what didn’t. Adjust your routine accordingly for continuous improvement.</li>
</ol>
<h3 id="heading-embrace-technology-wisely">Embrace Technology Wisely</h3>
<ol>
<li><strong>Organizational tools</strong>: Leverage project management tools and digital calendars to organize tasks and deadlines. A well-organized workflow aids concentration.</li>
<li><strong>Learning and adaptation</strong>: Stay informed about the latest technological tools that aid productivity. Be open to adopting new tools and methodologies that can enhance your focus and efficiency.</li>
<li><strong>Mindful usage</strong>: Practice intentional and mindful use of technology. Set clear boundaries for tech usage, focusing on tools that align with your goals and contribute positively to your productivity.</li>
</ol>
<h3 id="heading-practice-deep-work">Practice Deep Work</h3>
<p>Deep work is a concept centered on the ability to focus intensely on a cognitively demanding task, eliminating all distractions. This focused state not only enhances productivity but also improves the quality of the output. </p>
<p>Here's a step-by-step plan on how to effectively implement deep work into your routine:</p>
<ol>
<li><strong>Define deep work goals</strong>: Begin by identifying tasks or projects that require deep, uninterrupted concentration. These should be tasks that challenge your cognitive abilities and contribute significantly to your personal or professional growth.</li>
<li><strong>Schedule dedicated time blocks</strong>: Allocate specific time periods in your day solely for deep work. During these blocks, your goal is to work on your chosen tasks with complete focus. This could range from an hour to several hours, depending on your capacity and the nature of the task.</li>
<li><strong>Create a conducive environment</strong>: Optimize your environment to minimize distractions. This could involve working in a quiet room, turning off notifications on digital devices, or using tools like noise-cancelling headphones to create a distraction-free zone.</li>
<li><strong>Establish clear objectives</strong>: Before each deep work session, define what you aim to achieve. Having clear objectives helps maintain focus and gives you a sense of direction during your deep work session.</li>
<li><strong>Employ a ritual to start</strong>: Develop a ritual to signal the start of your deep work phase. This could be a simple action like brewing a cup of coffee, a short meditation, or organizing your workspace – anything that mentally prepares you to dive into a state of deep concentration.</li>
<li><strong>Work intensely, then take breaks</strong>: Engage in your task with full intensity but also schedule brief breaks to avoid cognitive burnout. Again, the Pomodoro technique can be helpful here.</li>
<li><strong>Review and reflect</strong>: At the end of your deep work session, take time to review what you've accomplished and reflect on the process. Assess what worked well and what could be improved for future sessions.</li>
<li><strong>Gradually increase duration</strong>: Start with shorter periods of deep work and gradually increase the duration as your concentration muscles strengthen. This gradual increase helps in adapting to the demands of deep work without feeling overwhelmed.</li>
</ol>
<p>Incorporating deep work into your routine can dramatically boost your productivity and the quality of your work. By following these steps, you're not just completing tasks – you're also developing a valuable skill that sets you apart in today's distraction-filled world.</p>
<p>The mastery of laser focus in our constantly buzzing world is not just beneficial – it's essential for success and fulfillment. As we've explored, effective focus is about channeling energy into the right tasks, safeguarding it from the myriad distractions vying for our attention. When we let distractions rule, they not only sap our energy but also steer our lives off course. </p>
<p>This chapter empowers you to reclaim control. By setting clear goals and dedicating your energy to them, you can enhance your ability to concentrate, leading to marked improvements in all areas of your life. </p>
<p>Remember, it's not just about working hard – it's about working smart, with a laser-sharp focus that cuts through the noise and leads to true accomplishment.</p>
<h2 id="heading-18-skill-building-how-to-elevate-your-talents">18. Skill Building: How to Elevate Your Talents</h2>
<p>Embarking on a journey to elevate your talents and transform from a novice to a skilled professional in just 20 hours may seem like a daunting task. But the world of skill acquisition is not reserved for the gifted few, but is an open field where anyone with dedication and a systematic approach can excel. </p>
<p>Whether you wish to try playing a musical instrument like the ukelele, refine your cooking skills, or learn a new programming language, the path to proficiency is more accessible than you might think.</p>
<h3 id="heading-the-20-hour-rule-demystifying-skill-acquisition">The 20-Hour Rule: Demystifying Skill Acquisition</h3>
<p>The key to developing a new skill lies in a focused and efficient practice of 20 hours. This concept, known as the 20-hour rule, is a stark contrast to the daunting 10,000-hour rule, which is about reaching the zenith of ultra-competitive fields. </p>
<p>The 10,000-hour rule, popularized by Malcolm Gladwell in his book "Outliers," suggests that it takes 10,000 hours of practice to achieve mastery in a field. But this rule is more applicable to people aiming to reach the top of highly competitive fields, such as professional athletes or world-class musicians.</p>
<p>The 20-hour rule, on the other hand, is about acquiring a new skill to a competent level, which requires much less time. This concept is not about attaining mastery but about reaching a stage where you are skilled enough to enjoy and further develop your chosen activity. It's about going from knowing nothing about a skill to being reasonably good at it.</p>
<h3 id="heading-step-by-step-guide-to-skill-building">Step-by-Step Guide to Skill Building</h3>
<p>The process of skill-building involves several steps, each of which can be illustrated with practical examples.</p>
<h4 id="heading-deconstruct-the-skill">Deconstruct the Skill</h4>
<p>Start by breaking down the skill into smaller, manageable components. For instance, if you're learning to play the ukulele, you might break down the skill into understanding the instrument, learning to tune it, going over basic chords, and learning to strum. </p>
<p>Identify the most essential parts that will have the most significant impact on your progress. This targeted approach ensures that you spend time on aspects that offer the most substantial improvement.</p>
<h4 id="heading-learn-just-enough-to-self-correct">Learn Just Enough to Self-Correct</h4>
<p>Gather resources – books, videos, courses – but avoid the trap of using them to procrastinate. The goal is to learn just enough to recognize your mistakes and self-correct during practice. </p>
<p>For example, if you're learning a new language, you might start by learning basic grammar and vocabulary, enough to form simple sentences and correct common mistakes.</p>
<h4 id="heading-remove-barriers-to-practice">Remove Barriers to Practice</h4>
<p>Identify and eliminate distractions. Create a conducive environment for focused practice. </p>
<p>For instance, if you're learning to cook, ensure you have all the necessary ingredients and tools before you start. The fewer obstacles you have, the more likely you are to engage in consistent practice.</p>
<h4 id="heading-commit-to-20-hours-of-practice">Commit to 20 Hours of Practice</h4>
<p>Overcome the initial frustration barrier by committing to a minimum of 20 hours of practice. This commitment is crucial to push through the early stage where progress feels slow, and the task feels challenging. </p>
<p>For example, when learning to play the ukulele, the first few hours might be spent on understanding the instrument, learning to tune it, and mastering a few basic chords. The initial stages might be frustrating, but with commitment, you can push through this phase and start making music.</p>
<h3 id="heading-practical-tips-for-effective-learning">Practical Tips for Effective Learning</h3>
<h4 id="heading-start-with-the-core-skills">Start with the Core Skills</h4>
<p>Focus on the core elements that make up the bulk of the skill. For example, learning a few key chords can enable you to play many songs on the ukulele, as opposed to mastering hundreds of chords.</p>
<h4 id="heading-use-the-pareto-principle">Use the Pareto Principle</h4>
<p>Apply the 80/20 rule – 20% of focused effort yields 80% of results. Identify this 20% in your chosen skill for efficient learning. In the case of language learning, this might mean focusing on the most commonly used words and grammatical structures.</p>
<h4 id="heading-set-small-achievable-goals">Set Small, Achievable Goals</h4>
<p>Break down your learning process into small, manageable goals. This approach provides a sense of achievement and keeps motivation high. For instance, if you're learning to cook, you might set a goal to try out one new recipe each week.</p>
<h4 id="heading-embrace-the-discomfort">Embrace the Discomfort</h4>
<p>Accept that feeling awkward and making mistakes is part of the learning process. Embrace these as opportunities to grow. </p>
<p>For example, when learning a new language, you might initially struggle with pronunciation or grammar, but these challenges are opportunities for improvement.</p>
<h4 id="heading-practice-deliberately">Practice Deliberately</h4>
<p>Engage in deliberate practice where you focus on specific areas for improvement. This type of practice is more effective than mindlessly repeating an activity. </p>
<p>For instance, when learning to play the ukulele, you might focus on improving your strumming technique or mastering a particular chord progression.</p>
<h4 id="heading-seek-feedback">Seek Feedback</h4>
<p>Feedback is essential for improvement. Use tools, mentors, or peers to gain insights into your performance and areas of improvement. </p>
<p>For example, if you're learning to cook, you might ask a more experienced friend or family member to taste your dishes and provide feedback.</p>
<h4 id="heading-reflect-and-adapt">Reflect and Adapt</h4>
<p>Regularly reflect on your practice sessions. What worked? What didn’t? Adapt your approach based on these reflections. </p>
<p>For instance, if you're learning a new language and find that you're struggling with pronunciation, you might decide to spend more time on listening and pronunciation exercises.</p>
<h4 id="heading-stay-consistent">Stay Consistent</h4>
<p>Consistency is more critical than the length of practice sessions. Regular, shorter practices can be more effective than infrequent, longer sessions. </p>
<p>For example, practicing the ukulele for 30 minutes every day is likely to be more effective than practicing for several hours once a week.</p>
<h4 id="heading-celebrate-progress">Celebrate Progress</h4>
<p>Acknowledge and celebrate your improvements, no matter how small. This positive reinforcement boosts your morale and motivation. </p>
<p>For instance, when learning a new language, you might celebrate being able to hold a basic conversation or understanding a song in the target language.</p>
<p>Skill-building is a journey of transformation, one that requires commitment, focus, and a strategic approach. By dedicating just 20 hours of focused practice and employing the steps outlined, you can elevate your talents and enjoy the fruits of your labor. </p>
<p>Remember, the barrier to learning a new skill is more emotional than intellectual. Embrace the initial discomfort, commit to the process, and witness your abilities grow exponentially. Now, what skill will ignite your passion? Take the first step today and start your journey towards skillful mastery.</p>
<h2 id="heading-19-solid-confidence-making-a-strong-impression">19. Solid Confidence: Making a Strong Impression</h2>
<p>In the realm of personal and professional growth, confidence is not just an asset – it’s a necessity. This essential trait is often misconstrued as innate, but in reality, it is a skill that can be cultivated and honed. </p>
<p>From industry leaders like Steve Jobs to innovators like Sam Altman, confidence is a common thread that weaves through the fabric of their successes. It’s a sword for creators, cutting through challenges and transforming visions into reality. </p>
<p>But it’s crucial to distinguish confidence from arrogance – while the former drives you forward with humility and purpose, the latter can derail your journey.</p>
<h3 id="heading-understanding-confidence">Understanding Confidence</h3>
<p>Confidence is often seen as a shield against the arrows of doubt and criticism. But it's more than just a defensive mechanism; it's a proactive force that propels you towards your goals. It’s about believing in your capabilities and expressing your true potential. </p>
<p>Remember, your business competitors and life's naysayers thrive on your lack of confidence. By undermining your self-esteem, they aim to keep you from reaching your full potential. But you have the power to counteract this by building an unshakable confidence that radiates in all your endeavors.</p>
<p>Ancient Greek philosophers also had profound insights on confidence and wisdom that align with these modern interpretations. </p>
<p>Socrates, for instance, famously stated, "The only true wisdom is in knowing you know nothing." This profound insight suggests that true confidence is not about boasting your knowledge or skills, but about having the humility to acknowledge the limits of our understanding. </p>
<p>This recognition opens the door to continual learning and growth, which are vital components of genuine confidence.</p>
<p>Similarly, the saying "To find yourself, think for yourself," often attributed to Socrates, emphasizes the importance of self-reflection and independent thinking in developing confidence. It encourages us to trust our own judgments and beliefs, rather than relying solely on external validation or following the crowd. </p>
<p>This approach fosters a deep-seated confidence that is grounded in self-awareness and personal authenticity.</p>
<p>Solid confidence isn't just about how you present yourself to the world. It's also deeply rooted in how well you know and manage yourself. </p>
<p>Here's how you can develop this vital skill:</p>
<h4 id="heading-know-yourself-gnothi-seauton-gn8i-sayton-in-greek">Know Yourself (Gnothi Seauton, Γνῶθι σαυτόν, in Greek)</h4>
<p>Self-awareness is the cornerstone of confidence. Spend time in introspection to understand what truly drives you. </p>
<p>Use tools like journaling to articulate your thoughts and feelings. Meditation and mindful walks can help clear your mind and bring insights into your core values and beliefs. </p>
<p>It's essential to identify not only your strengths but also acknowledge your weaknesses. Recognizing your weaker areas allows you to develop strategies to manage them effectively, ensuring they don’t hinder your progress.</p>
<h4 id="heading-habitual-excellence-aristotle">Habitual Excellence (Aristotle)</h4>
<p>Aristotle's notion that excellence is a habit serves as a powerful reminder that consistency in effort leads to greatness. Establish challenging yet realistic goals and divide them into smaller, achievable tasks. This approach helps in maintaining motivation and tracking progress. </p>
<p>Celebrating small victories reinforces your belief in your capabilities and strengths. Epictetus's words remind us to focus on tangible issues rather than be paralyzed by unfounded worries.</p>
<h4 id="heading-face-your-fears-aristotle">Face Your Fears (Aristotle)</h4>
<p>Confronting what scares you is a significant step towards building confidence. Recognize that failure is not a setback but a part of the learning process. </p>
<p>It’s crucial to remember that each failure brings valuable lessons and experience. Embrace repetition and practice as a means to master your fears. The freedom that comes from overcoming fears, as Aristotle suggests, is a true measure of inner strength and confidence.</p>
<h4 id="heading-cultivate-calm-and-moderation-sophrosyne-swfrosynh-in-greek">Cultivate Calm and Moderation (Sophrosyne, σωφροσύνη, in Greek)</h4>
<p>In times of stress and chaos, maintaining a sense of calm and balance is key. Develop self-restraint to avoid overreaction and strive for a balanced approach in all aspects of life. </p>
<p>Maintaining work-life balance and ensuring adequate rest are not just essential for health but also for sustaining focus and productivity.</p>
<h4 id="heading-express-your-potential">Express Your Potential</h4>
<p>Believing in yourself is fundamental to expressing one’s potential. Reflect on your past achievements to remind yourself of your capabilities. </p>
<p>Visualizing future success can be a powerful motivator. Learn to silence the inner critic that sows seeds of doubt and instead, become your most supportive cheerleader.</p>
<h4 id="heading-embrace-humility">Embrace Humility</h4>
<p>Recognizing that you don’t know everything is a strength, not a weakness. Staying humble, irrespective of your achievements, keeps you grounded and open to continuous learning. </p>
<p>Oscar Wilde’s quote underlines the importance of understanding that self-knowledge is an ongoing journey:</p>
<blockquote>
<p>“The aim of life is self-development. To realise one's nature perfectly-that is what each of us is here for. People are afraid of themselves, nowadays. They have forgotten the highest of all duties, the duty that one owes to one's self. Of course they are charitable. They feed the hungry, and clothe the beggar. But their own souls starve, and are naked.”</p>
</blockquote>
<h4 id="heading-pursue-virtue-wisdom-and-ethical-conduct-eudaimonia-edaimonia-in-greek">Pursue Virtue, Wisdom, and Ethical Conduct (Eudaimonia, εὐδαιμονία in Greek)</h4>
<p>Align your actions and goals with ethical conduct and wisdom. This alignment brings deeper satisfaction and a sense of fulfillment. Look for role models who embody these virtues. Continuous learning, both formal and informal, helps in the pursuit of wisdom.</p>
<h4 id="heading-develop-curiosity-in-others">Develop Curiosity in Others</h4>
<p>Building genuine connections with others not only enhances relationships but also contributes to self-growth. Show genuine interest in people’s stories and experiences. This not only builds empathy but also deepens your understanding of human nature and different perspectives.</p>
<h4 id="heading-debate-respectfully">Debate Respectfully</h4>
<p>Engaging in healthy debates and discussions can expand your horizons. Be open to other viewpoints and defend your perspectives with respect and humility. Be willing to change your opinion in the light of new evidence or arguments, which is a sign of strength, not weakness.</p>
<h4 id="heading-live-in-the-present">Live in the Present</h4>
<p>Focus on the present moment with mindfulness. Practicing mindfulness and self-control helps in managing stress and improves concentration. Avoid multitasking and try to be fully immersed in the task at hand. This helps in enhancing performance and building a deeper sense of satisfaction in your work.</p>
<p>In summary, confidence is a cultivated skill, not a given trait. It grows through self-awareness, consistent facing of challenges, and an unshakeable commitment to personal growth. Understanding your strengths and weaknesses is key, as it enables you to leverage your full potential while staying grounded in humility.</p>
<p>This journey of self-discovery and resilience empowers you to thrive in both personal and professional realms. True confidence is quiet yet powerful, steering you towards success and enabling you to leave a lasting, positive impression. Remember, it's the balanced blend of self-assurance and humility that truly defines and drives impactful, enduring confidence.</p>
<h2 id="heading-20-boosting-productivity-how-to-enhance-your-efficiency">20. Boosting Productivity: How to Enhance Your Efficiency</h2>
<p>Unleashing the power of productivity isn't just about working harder – it's about working smarter. </p>
<p>In this chapter, we'll delve into twelve tried-and-tested productivity methods that can transform the way you approach tasks and manage time. Each method offers unique advantages, allowing you to select and customize strategies that resonate with your working style and life's demands. </p>
<p>Productivity isn't a one-size-fits-all concept. Rather, it's a personal journey towards efficiency and effectiveness.</p>
<h4 id="heading-getting-things-done-gtd-method">Getting Things Done (GTD) Method</h4>
<p>David Allen's GTD method is about clearing your mind and organizing tasks in a manageable system. It involves capturing everything that needs to be done – from big projects to minor tasks – and categorizing them. </p>
<p>This method emphasizes reviewing these tasks regularly and taking actionable steps. It's a comprehensive approach to decluttering your mind and focusing on the 'now' of productivity.</p>
<h4 id="heading-pomodoro-technique">Pomodoro Technique</h4>
<p>We've discussed this technique already, but it's relevant here as well. Developed by Francesco Cirillo, the Pomodoro technique uses a timer to break work into intervals, traditionally 25 minutes in length, separated by short breaks. This method is excellent for maintaining focus and preventing burnout, as it balances work with essential rest.</p>
<h4 id="heading-task-batching">Task Batching</h4>
<p>Task batching involves grouping similar tasks together to minimize distraction and improve concentration. For instance, set aside specific times for emails, calls, or meetings. This method helps in reducing the mental load of switching between different types of tasks.</p>
<h4 id="heading-eat-the-frog">Eat the Frog</h4>
<p>Based on Mark Twain's famous quote, this strategy involves tackling your most challenging or unpleasant task first. This approach ensures that the most daunting task is out of the way, providing a sense of accomplishment and freeing up mental energy for other tasks.</p>
<h4 id="heading-eisenhower-decision-matrix">Eisenhower Decision Matrix</h4>
<p>This method helps prioritize tasks based on their urgency and importance, categorizing them into four quadrants. It's an effective way to visualize what needs immediate attention and what can be scheduled or delegated.</p>
<h4 id="heading-time-blocking">Time Blocking</h4>
<p>Time blocking is about dedicating specific blocks of time to particular tasks or activities. This method helps in managing your time efficiently and ensures that each task gets the attention it deserves.</p>
<h4 id="heading-time-boxing">Time Boxing</h4>
<p>Similar to time blocking, time boxing allocates a fixed time period to a task, and once the time is up, you move on to the next task. This approach is particularly 3useful for controlling time spent on tasks that could expand indefinitely.</p>
<h4 id="heading-bullet-journaling">Bullet Journaling</h4>
<p>A customizable organization system that combines planning, journaling, and task management. Bullet journaling is effective for those who prefer a more hands-on and creative approach to productivity.</p>
<h4 id="heading-personal-kanban">Personal Kanban:</h4>
<p>Originating from manufacturing, Kanban uses boards and cards to visualize workflow. In a personal context, it can help manage tasks and projects, providing a clear overview of progress and priorities.</p>
<h4 id="heading-smart-goals">SMART Goals</h4>
<p>Setting Specific, Measurable, Achievable, Relevant, and Time-bound goals ensures clarity and focus. It’s a structured approach to setting objectives that are both challenging and attainable.</p>
<h4 id="heading-the-action-method">The Action Method</h4>
<p>This approach focuses on breaking down projects into actionable steps. It's about moving away from endless planning and towards doing, emphasizing action over excessive deliberation.</p>
<h4 id="heading-must-should-want">Must, Should, Want</h4>
<p>Prioritize tasks by categorizing them into 'Must do', 'Should do', and 'Want to do'. This method helps balance necessity and desire, ensuring that you’re not only productive but also satisfied.</p>
<p>Incorporating these methods into your daily routine requires experimentation and adaptation. </p>
<p>Start by selecting one or two methods that resonate with you. Adapt them to your personal and professional life, and observe the changes in your productivity levels. </p>
<p>Remember, the key is consistency and willingness to refine your approach as you discover what works best for you. By embracing these productivity strategies, you equip yourself with powerful tools to enhance your efficiency and effectiveness, paving the way for greater achievements and a more balanced life.</p>
<h2 id="heading-21-fall-like-a-thunderbolt-how-to-make-decisions-efficiently">21. Fall Like a Thunderbolt: How to Make Decisions Efficiently</h2>
<p>In the relentless race of creation and innovation, speed emerges not just as an ally, but as a game-changer. </p>
<p>This chapter is rooted in the understanding that velocity in decision-making and execution can make the difference between leading the pack and lagging behind. But it's crucial to clarify that speed here doesn't imply a compromise in quality or depth. Instead, it's about harnessing speed effectively and strategically to outpace competition and meet evolving market demands swiftly.</p>
<p>In the creative world, the dilemma often faced is whether to produce rapidly to meet immediate demands or to meticulously craft a product over time. The answer lies in striking a balance, using speed as a lever to propel forward without forsaking the essence of quality and innovation. </p>
<p>Look at OpenAI, for instance. Its reputation as a leading entity is not just due to the groundbreaking nature of its offerings but also its ability to rapidly innovate and adapt. It's a testament to the fact that in today's fast-paced world, those who can quickly pivot and respond to change are the ones who thrive.</p>
<p>This notion is critical for creators and innovators. You must recognize that specializing in a particular area can amplify the impact of your speed. </p>
<p>Unlike a giant like Google, which has an army of engineers to drive its productivity, a more focused approach allows smaller teams or people to use their agility as a competitive edge. It's about being nimble, flexible, and quick to act, much like a rocket cutting through the sky, unencumbered by the drag of inertia or doubt.</p>
<p>A significant barrier to this approach is often internal – the beliefs and mindsets that hold creators back. The misconception of "I can't do this because..." is a self-imposed limitation that needs to be shattered. Every problem has a solution, and in this guide, we've been exploring ways to find these solutions, urging you to move past excuses and embrace the realm of possibilities.</p>
<p>Also, the current landscape of technological advancement, particularly in AI, opens up avenues for efficiency and speed that were previously unimaginable. </p>
<p>This era of AI is not just about the capabilities of the technology but also about the mindset to leverage it effectively. It's about being ruthless in addressing weaknesses and using technology as a tool to develop unique products that resonate with customers' needs.</p>
<p>Speed, in essence, is about making waves in your market, adapting quickly to changes, and seizing your share of the spotlight. In a world where customers' expectations are sky-high, being able to deliver rapidly and efficiently is not just an advantage – it's a necessity. </p>
<p>The Thunderbolt Effect is more than just about speed – it's also about momentum, seizing opportunities, and moving with unwavering determination, much like historical figures such as Alexander the Great, Thomas Edison, and Steve Jobs. These innovators used their rapid pace of change and execution to create lasting impacts in their respective fields.</p>
<p>This chapter is a deep dive into the strategies, mindset, and practical steps you need to harness the Thunderbolt Effect in your journey as a creator. It's about being fast, but more importantly, being smart and strategic with your speed.</p>
<p>In today's hyper-competitive and fast-paced digital era, the need to accelerate processes, optimize time, and leverage technology for efficiency is more crucial than ever, especially for creators and entrepreneurs. Let's delve into some potent strategies that can significantly enhance productivity and speed up success.</p>
<h3 id="heading-task-automation">Task Automation</h3>
<h4 id="heading-maximize-efficiency-with-automation-tools">Maximize Efficiency with Automation Tools</h4>
<p>Tools like Zapier or IFTTT are essential for modern creators. Most startup tasks, possibly up to 90%, can be automated with publicly available tools. This not only saves invaluable time but also allows you to focus on tasks that genuinely require your unique skills.</p>
<h4 id="heading-creating-custom-solutions">Creating Custom Solutions</h4>
<p>If a suitable automation tool doesn't exist, consider developing one using no-code tools. The vast majority of processes can be automated, and as a creator, your time is a precious commodity that should be spent wisely.</p>
<h3 id="heading-no-code-revolution">No-Code Revolution</h3>
<h4 id="heading-leveraging-no-code-for-rapid-development">Leveraging No-Code for Rapid Development</h4>
<p>As a software engineer, the appeal of no-code tools is undeniable. These platforms enable rapid development and testing of ideas without the time-intensive process of traditional coding. This approach is especially beneficial for validating a concept and addressing customer needs efficiently before coding your own solution as needed.</p>
<h4 id="heading-the-potential-of-no-code-startups">The Potential of No-Code Startups</h4>
<p>Many successful startups today are built entirely on no-code platforms. These tools allow smart, hard-working entrepreneurs to make significant strides, sometimes even reaching the finish line without a line of code.</p>
<h3 id="heading-streamlining-and-minimalism">Streamlining and Minimalism</h3>
<h4 id="heading-aiming-for-the-minimum-viable-product-mvp">Aiming for the Minimum Viable Product (MVP)</h4>
<p>The key is to focus on what’s essential. Sometimes, a super-clean website or an additional feature isn’t necessary initially. Aim for the MVP, achieve your primary goals, and then scale using resources aligned with your mission and values.</p>
<h3 id="heading-efficient-time-management">Efficient Time Management</h3>
<h4 id="heading-strategic-use-of-digital-calendars-and-to-do-lists">Strategic Use of Digital Calendars and To-Do Lists</h4>
<p>Tools like Google Calendar and Todoist are more than organizational tools – they are strategic assets. Be intentional with your time, focusing on activities that add value to your product, personal growth, or goals. Incorporate deep work and strategic breaks to enhance productivity.</p>
<h3 id="heading-decision-making-frameworks">Decision-Making Frameworks</h3>
<h4 id="heading-applying-ooda-for-swift-decisions">Applying OODA for Swift Decisions</h4>
<p>Quick and effective decision-making is crucial. Frameworks like OODA (Observe, Orient, Decide, Act) help in making faster decisions without lingering on them for days or months.</p>
<h3 id="heading-cloud-computing-services">Cloud Computing Services</h3>
<h4 id="heading-utilizing-cloud-services-for-agility">Utilizing Cloud Services for Agility</h4>
<p>Platforms like AWS and Google Cloud offer rapid access to computing resources and data storage. The field of DevOps has revolutionized product development, automating processes that used to take considerable time.</p>
<h3 id="heading-rapid-learning-and-skill-acquisition">Rapid Learning and Skill Acquisition</h3>
<h4 id="heading-online-platforms-for-continuous-learning">Online Platforms for Continuous Learning</h4>
<p>Instead of traditional education paths, platforms like freeCodeCamp, Coursera, Udemy, and Khan Academy offer a modern, flexible approach to skill acquisition, perfectly suited for the 21st century.</p>
<h3 id="heading-automated-customer-service">Automated Customer Service</h3>
<h4 id="heading-chatbots-and-automated-solutions">Chatbots and Automated Solutions</h4>
<p>In many cases, customer service assistants can be replaced with automated solutions like chatbots, freeing up resources to enhance the product itself.</p>
<h3 id="heading-speed-optimization-in-digital-presence">Speed Optimization in Digital Presence</h3>
<h4 id="heading-optimizing-website-performance">Optimizing Website Performance</h4>
<p>Utilize plugins and tools to improve website loading times and overall performance. In the digital age, this is a basic yet crucial aspect of your online presence.</p>
<h3 id="heading-workflow-and-project-management">Workflow and Project Management</h3>
<h4 id="heading-streamlining-team-collaboration">Streamlining Team Collaboration</h4>
<p>Use tools like Monday.com or Asana to optimize workflow and project management. These tools facilitate better team collaboration and efficiency.</p>
<h3 id="heading-ai-driven-analytics">AI-Driven Analytics</h3>
<h4 id="heading-harnessing-ai-for-analytics">Harnessing AI for Analytics</h4>
<p>Tools like Google Analytics and Tableau offer swift and insightful data analysis, essential for making informed decisions quickly.</p>
<p>Developing efficient decision-making skills through the Thunderbolt Strategy is an essential pursuit in the fast-evolving landscape of creation and innovation. This approach is not about hastily crafted outcomes but a strategic acceleration of processes, balanced with quality and depth.</p>
<p>For creators and entrepreneurs, the essence lies in smartly harnessing technological advancements and innovative strategies to propel forward. </p>
<p>Task automation, no-code platforms, and efficient time management, complemented by rapid decision-making frameworks and cloud computing services, form the backbone of this strategy.</p>
<p>The crux is to specialize, be nimble, and leverage speed as a competitive advantage, much like the inspiring examples of historical innovators. Embracing this mindset enables creators to adapt swiftly, meet market demands, and carve a distinct path to success. </p>
<p>The Thunderbolt Strategy is about being fast and strategic, ensuring that speed is a tool for innovation and impact, aligning with the ever-growing expectations of a digital era that values quick, efficient, and impactful solutions.</p>
<p>In whatever you do, fall like a lightning bolt.</p>
<h2 id="heading-22-breaking-boundaries-how-to-make-your-mark">22. Breaking Boundaries: How to Make Your Mark</h2>
<p>Innovation and greatness, often shrouded in an aura of exceptionality, are frequently perceived as the domain of a select few. This perception creates an illusion that boundary-breakers are born, not made. </p>
<p>This chapter aims to dispel this myth and assert that the journey to breaking boundaries and achieving greatness is not a birthright, but a path accessible to all. </p>
<p>It's not about being born with a unique gift, but about demonstrating flexibility, maintaining a strong belief, and taking focused action. It's about harnessing the power of perseverance, resilience, and determination to transform the ordinary into the extraordinary.</p>
<h3 id="heading-historical-and-modern-icons">Historical and Modern Icons</h3>
<p>Throughout history, people who have left indelible marks on the world share a common trait – a relentless focus on a limited set of goals. </p>
<p>Historical figures like Alexander the Great, who conquered vast territories, and Julius Caesar, who prepared the Roman Republic to become the Roman Empire, exemplify this trait. </p>
<p>In the modern era, icons like Ada Lovelace, Bill Gates, and Steve Jobs and have revolutionized technology with their unwavering focus and determination. </p>
<p>This focus is akin to the concentrated energy in quantum physics that leads to transformative outcomes. Just as quantum physics explores the potential of atoms to create revolutionary materials, people can channel their energies towards specific actions or goals, leading to significant breakthroughs. </p>
<p>These breakthroughs, whether in the realm of science, technology, or societal change, are the result of focused energy and relentless pursuit of goals.</p>
<h3 id="heading-set-boundaries">Set Boundaries</h3>
<p>Setting and maintaining healthy personal and professional boundaries is akin to the Law of Conservation in physics. It states that energy cannot be created or destroyed, only transferred or transformed. </p>
<p>In the context of personal growth and achievement, this law translates into the effective management of your energy, focus, and attention. It's about deliberately choosing where to invest your limited resources, ensuring that each investment contributes to your overall goals. </p>
<p>This process involves setting clear boundaries, prioritizing tasks, and making conscious decisions about where to direct your energy. By doing so, you can enhance your efficiency and productivity, thereby accelerating your journey towards breaking boundaries.</p>
<h3 id="heading-practice-mindfulness">Practice Mindfulness</h3>
<p>Mindfulness, the practice of being fully present and engaged in the current moment, is a crucial tool in this process. It involves being acutely aware of your internal state – your thoughts, feelings, and physical sensations – as well as your external environment. </p>
<p>This heightened awareness allows you to discern which activities support your journey towards breaking boundaries and which ones detract from it. It helps you identify energy drains and distractions, enabling you to redirect your focus towards activities that align with your goals. </p>
<p>Mindfulness also aids in managing energy levels and sharpening focus, both of which are essential for breaking boundaries. By cultivating mindfulness, you can navigate your path with greater clarity and purpose.</p>
<h3 id="heading-quantum-breaking">Quantum Breaking</h3>
<p>The concept of quantum breaking, derived from quantum physics, metaphorically mirrors the journey of boundary-breaking people. Quantum breaking refers to the phenomenon where a system escapes from a confined state due to quantum fluctuations. </p>
<p>In the context of personal growth and achievement, this concept suggests that tiny, focused actions, though seemingly insignificant, can accumulate over time, leading to significant transformations. This aligns with the idea that small, consistent steps can lead to groundbreaking achievements. </p>
<p>Just as a single photon can trigger a quantum break, a single step, however small, can set the stage for a major breakthrough. </p>
<h3 id="heading-take-focused-action">Take Focused Action</h3>
<p>In the realm of breaking boundaries, the principle of focused action is pivotal. Mirroring the concentrated energy in quantum physics that leads to revolutionary changes, boundary-breakers channel their efforts into a specific set of goals. </p>
<p>This focused approach is akin to directing a beam of light through a magnifying glass, intensifying its power and impact. By honing your energies towards targeted actions, you catalyze significant breakthroughs. This concentration of effort turns aspirations into tangible achievements, demonstrating that the power of focused action is a cornerstone of transformative success.</p>
<h3 id="heading-embrace-failure-as-a-catalyst-for-growth">Embrace Failure as a Catalyst for Growth</h3>
<p>Adopting the mindset of a sculptor who sees a masterpiece within a block of stone, boundary-breakers perceive each failure as a chisel shaping their path to greatness. They approach setbacks not as final defeats but as invaluable lessons, opportunities to refine their strategy and enhance their approach. </p>
<p>This attitude cultivates a culture where experimentation is encouraged, resilience is built, and the fear of failure becomes a propellant for innovation rather than a deterrent. Each misstep is seen as a vital ingredient in the recipe for success, essential for the iterative process that leads to mastery and achievement.</p>
<h3 id="heading-practice-strategic-risk-taking">Practice Strategic Risk-Taking</h3>
<p>The narrative of boundary-breakers often features daring risks, but it's their strategic approach to risk-taking that truly defines their journey. As a boundary-breaker, you don't engage in reckless gambles. Instead, you weigh the potential risks against the possible rewards with precision and insight. </p>
<p>Recognizing that growth often requires stepping out of your comfort zone, you discern which risks are essential stepping stones towards their objectives. This calculated approach ensures that even in the face of challenges, you are equipped with the knowledge and resilience necessary for recovery and progression. </p>
<p>Your ability to strategically navigate through uncharted waters exemplifies the art of turning risks into pathways for groundbreaking achievements.</p>
<p>In conclusion, breaking boundaries and making your mark are not exclusive privileges reserved for the 'special few.' This is a path open to anyone willing to focus their energy, set healthy boundaries, practice mindfulness, and persistently work towards their goals. It's about striving for excellence in the small things, consistently overcoming fear, and paving the way for greatness through daily, focused actions. </p>
<p>As creators and innovators, breaking boundaries is not just an aspiration but a necessity. It's about challenging the status quo, pushing the limits of what's possible, and redefining the boundaries of our respective fields. It's about transforming the world, one boundary at a time.</p>
<h2 id="heading-conclusion">Conclusion</h2>
<p>As we reach the conclusion of this book, I extend my heartfelt gratitude for your commitment and engagement. Crafting this guide has been a journey of exploration and refinement, fueled by the dynamic environment and supportive community fostered by freeCodeCamp, along with the invaluable contributions of editors and team members.</p>
<p>This book was designed to be more than just a collection of principles. It's a holistic blueprint for unleashing your potential. By providing a comprehensive framework encompassing mindset, systems, and practical strategies for product development, we aimed to equip you with the tools necessary for breaking boundaries and pushing reality to its limit and achieving excellence in your chosen fields.</p>
<p>The core of this guide rests on the power of a well-structured 10-year plan, the continual upgrading of skills, and the cultivation of a versatile and resilient mindset. These elements, combined with productive habits, prepare you to thrive amidst chaos and adapt with agility. The essence of our message is to approach each challenge with speed and precision, avoiding stagnation and embracing swift, decisive action.</p>
<p>Remember, the application of these principles is not a piecemeal approach but a symphonic integration into your life and work. Each principle, when harmoniously combined with others, creates a powerful system that propels you towards unparalleled success and innovation.</p>
<p>As you move forward on your journey, let this guide be a constant companion, reminding you of the limitless potential that lies within disciplined application and strategic thinking. Whether you're just beginning your path as a creator or seeking to elevate your existing pursuits, the principles laid out in this guide offer a roadmap to transcending conventional boundaries and achieving extraordinary results.</p>
<p>In closing, I encourage you to not just read and reflect on these principles but to live them. Embrace each day as an opportunity to apply these strategies, and witness the transformation in your work and life. The path to becoming an exceptional creator is before you, and with the insights from this guide, you are well-equipped to traverse it with confidence and mastery.</p>
<p>Thank you for embarking on this journey with "The Creators Guide." As you continue to explore the realms of creativity and innovation, remember that our community is here to support, inspire, and celebrate your successes. If you want to join our ranks, you know where to find us.</p>
<h2 id="heading-resources"><strong>Resources</strong></h2>
<p>If you're keen on furthering your Java knowledge, here's a guide to help you <a target="_blank" href="https://join.lunartech.ai/java-fundamentals">conquer Java and launch your coding career</a>. It's perfect for those interested in AI and machine learning, focusing on effective use of data structures in coding. This comprehensive program covers essential data structures, algorithms, and includes mentorship and career support.</p>
<p>Additionally, for more practice in data structures, you can explore these resources:</p>
<ol>
<li><strong><a target="_blank" href="https://join.lunartech.ai/six-figure-data-science-bootcamp">Java Data Structures Mastery - Ace the Coding Interview</a></strong>: A free eBook to advance your Java skills, focusing on data structures for enhancing interview and professional skills.</li>
<li><a target="_blank" href="https://join.lunartech.ai/java-fundamentals"><strong>Foundations of Java Data Structures - Your Coding Catalyst</strong></a>: Another free eBook, diving into Java essentials, object-oriented programming, and AI applications.</li>
</ol>
<p>Visit LunarTech's website for these resources and more information on the <a target="_blank" href="https://lunartech.ai/">bootcamp</a>.</p>
<h3 id="heading-connect-with-me"><strong>Connect with Me:</strong></h3>
<ul>
<li><a target="_blank" href="https://ca.linkedin.com/in/vahe-aslanyan">Follow me on LinkedIn for a ton of Free Resources in CS, ML and AI</a></li>
<li><a target="_blank" href="https://vaheaslanyan.com/">Visit my Personal Website</a></li>
<li>Subscribe to my <a target="_blank" href="https://tatevaslanyan.substack.com/">The Data Science and AI Newsletter</a></li>
</ul>
<h2 id="heading-about-the-author"><strong>About the Author</strong></h2>
<p>I'm Vahe Aslanyan, specializing in the world of computer science, data science, and artificial intelligence. Explore my work at <a target="_blank" href="https://www.vaheaslanyan.com/">vaheaslanyan.com</a>. My expertise encompasses robust full-stack development and the strategic enhancement of AI products, with a focus on inventive problem-solving.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://vaheaslanyan.com/">https://vaheaslanyan.com/</a></div>
<p>My experience includes spearheading the launch of a prestigious data science bootcamp, an endeavor that put me at the forefront of industry innovation. I've consistently aimed to revolutionize technical education, striving to set a new, universal standard.</p>
<p>As we close this chapter, I extend my sincere thanks for your focused engagement. Imparting my professional insights through this book has been a journey of professional reflection. Your participation has been invaluable. I anticipate these shared experiences will significantly contribute to your growth in the dynamic field of technology.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Learn Java Fundamentals – Object-Oriented Programming [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ Are you just getting into software development? Or do you need to upgrade your coding skills? Java's significance within the tech sector stands unchallenged, so it's a great place to start. Java is at the foundation of Object-Oriented Programming (OO... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/learn-java-object-oriented-programming/</link>
                <guid isPermaLink="false">66b99b033cd81de09c96b2b8</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Java ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Object Oriented Programming ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Vahe Aslanyan ]]>
                </dc:creator>
                <pubDate>Thu, 09 Nov 2023 17:35:38 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/11/Learn-Java-and-OOP-Book-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Are you just getting into software development? Or do you need to upgrade your coding skills? Java's significance within the tech sector stands unchallenged, so it's a great place to start.</p>
<p>Java is at the foundation of Object-Oriented Programming (OOP). This is an approach to programming that mirrors our complexity by simulating objects that represent reality and have depth and functionality. </p>
<p>OOP is a practice that systematizes code – enhancing modularity and reusability. And it's a testament to its design that 90% of Fortune 500 firms rely on Java for their operations, according to Oracle reports.</p>
<p>OOP offers both novice and veteran coders alike an efficient strategy for designing code based on objects – templates which define both structure and behavior. This practice encourages order and efficiency – two hallmarks that Java embodies with grace.</p>
<p>This book goes far beyond a basic introduction to OOP in Java. It offers an in-depth tour through Java's core. </p>
<p>I'll be your guide, using my extensive field experience, and I'll provide you with insight into Java's continued relevancy in an ever-evolving tech landscape.</p>
<p>My journey took place through a combination of resources, each offering insights while never fully providing comprehensive understanding. This book represents my attempt at providing just such a resource.</p>
<p>This manual has been tailored specifically for you if you are new to Java or revisiting foundational concepts – whether that means learning for the first time, revisiting foundational ideas, or needing reliable references for Java development. Combining real world application with analytical depth, this book seeks to demystify its intricate details for you.</p>
<p>Mastering Java – a language at the core of IoT and driving over 2.5 billion Android devices – will not only enhance your coding abilities, but also increase your marketability. </p>
<p>With Java proficiency, developers see a 58% increase in job opportunities, according to industry reports. Entrepreneurs leveraging Java report a 35% faster time-to-market for their products, opening doors to new business ventures and innovation.</p>
<p>Ready to dive into Java? Let's start this coding journey together.</p>
<h2 id="heading-what-youll-learn">What You'll Learn</h2>
<h3 id="heading-chapter-1-java-basics">Chapter 1: Java Basics</h3>
<ol>
<li><a class="post-section-overview" href="#heading-your-first-java-program">Your First Java Program</a></li>
<li><a class="post-section-overview" href="#heading-understanding-java-syntax">Understanding Java Syntax</a></li>
</ol>
<h3 id="heading-chapter-2-java-data-types-and-variablesheading-chapter-2-java-data-types-and-variables"><a class="post-section-overview" href="#heading-chapter-2-java-data-types-and-variables">Chapter 2: Java Data Types and Variables</a></h3>
<ol>
<li><a class="post-section-overview" href="#heading-overview-of-the-eight-primitive-data-types">Primitive Data Types in Java</a> </li>
<li><a class="post-section-overview" href="#heading-non-primitive-data-types">Non-primitive data types</a></li>
<li><a class="post-section-overview" href="#heading-type-casting">Type Casting in Java</a></li>
</ol>
<h3 id="heading-chapter-3-java-operators-and-control-statementsheading-chapter-3-java-operators-and-control-statements"><a class="post-section-overview" href="#heading-chapter-3-java-operators-and-control-statements">Chapter 3: Java Operators and Control Statements</a></h3>
<ol>
<li><a class="post-section-overview" href="#heading-arithmetic-operators">Arithmetic Operators</a></li>
<li><a class="post-section-overview" href="#heading-relational-operators">Relational Operators</a></li>
<li><a class="post-section-overview" href="#heading-logical-operators">Logical Operators</a></li>
<li><a class="post-section-overview" href="#heading-control-statements-in-java-if-else-switch">Control Statements in Java – if, else, switch</a></li>
<li><a class="post-section-overview" href="#heading-loops-for-while-do-while-in-java-navigating-repetition">Loops: for, while, do-while</a></li>
</ol>
<h3 id="heading-chapter-4-object-oriented-programming-oopheading-chapter-4-object-oriented-programming-oop"><a class="post-section-overview" href="#heading-chapter-4-object-oriented-programming-oop">Chapter 4: Object-Oriented Programming (OOP)</a></h3>
<ol>
<li><a class="post-section-overview" href="#heading-what-is-object-oriented-programming">What is Object-Oriented Programming?</a></li>
<li><a class="post-section-overview" href="#heading-understanding-classes-in-java-the-blueprint">Classes and Objects</a></li>
<li><a class="post-section-overview" href="#heading-understanding-constructors">Constructors</a></li>
<li><a class="post-section-overview" href="#heading-what-is-inheritance-in-object-oriented-programming">Inheritance</a></li>
<li><a class="post-section-overview" href="#heading-what-is-polymorphism-in-object-oriented-programming">Polymorphism</a></li>
<li><a class="post-section-overview" href="#heading-what-is-encapsulation-in-object-oriented-programming">Encapsulation</a></li>
<li><a class="post-section-overview" href="#heading-what-is-abstraction-in-object-oriented-programming">Abstraction</a></li>
</ol>
<h3 id="heading-chapter-5-advanced-java-conceptsheading-chapter-5-advanced-java-concepts"><a class="post-section-overview" href="#heading-chapter-5-advanced-java-concepts">Chapter 5: Advanced Java Concepts</a></h3>
<ol>
<li><a class="post-section-overview" href="#heading-interfaces-in-java">Interfaces</a></li>
<li><a class="post-section-overview" href="#heading-abstract-classes-and-methods-in-java">Abstract Classes and Methods</a></li>
<li><a class="post-section-overview" href="#heading-exception-handling-in-java">Exception handling</a> </li>
</ol>
<h3 id="heading-chapter-6-closingheading-closing-1"><a class="post-section-overview" href="#heading-closing-1">Chapter 6: Closing</a></h3>
<ol>
<li><a class="post-section-overview" href="#heading-closing-1">Final words</a></li>
<li><a class="post-section-overview" href="#heading-about-the-author">About the Author</a></li>
</ol>
<h2 id="heading-by-the-end-of-this-book">By the End of This Book:</h2>
<ol>
<li><strong>Java Developer</strong>: You'll be able to craft server-side applications, manage backend operations, and uphold enterprise software standards with a robust understanding of Java syntax and OOP principles.</li>
<li><strong>Android Developer</strong>: You'll be skilled in designing and building innovative applications, creating user-centric mobile experiences with Java's versatile programming environment.</li>
<li><strong>Quality Assurance Engineer</strong>: You'll ensure software excellence by writing comprehensive automated tests, leveraging your foundational Java knowledge.</li>
<li><strong>Software Architect</strong>: You'll be adept at architecting and designing the structure of complex software systems, implementing advanced Java concepts to ensure robustness and scalability.</li>
<li><strong>Systems Analyst</strong>: You'll be capable of efficiently translating business requirements into technical specifications, optimizing system performance using Java's robust features.</li>
<li><strong>Data Analyst</strong>: You'll have the ability to manage and interpret large data sets, extracting actionable insights and contributing to strategic decision-making with Java's capabilities.</li>
<li><strong>Educator/Trainer</strong>: You'll be prepared to pass on your Java expertise, from the basics to the advanced intricacies, teaching in various educational formats.</li>
<li><strong>Freelance Software Developer</strong>: You'll be ready to tackle diverse and challenging projects, providing your Java programming expertise to a global clientele.</li>
<li><strong>Game Developer</strong>: You'll have the knowledge to enter the creative world of game design and development, creating engaging desktop and mobile games with Java's OOP capabilities.</li>
</ol>
<h2 id="heading-your-first-java-program">Your First Java Program</h2>
<p>This chapter will introduce you to Java programming, starting with the fundamental 'Hello, World!' program.</p>
<h3 id="heading-get-set-up">Get Set Up:</h3>
<p><strong>JDK Installation</strong>: Every Java developer starts with the Java Development Kit (JDK). It equips your machine to understand and execute Java code. Ensure you have the latest JDK installed.</p>
<p>Here's a guide that'll help you <a target="_blank" href="https://www.freecodecamp.org/news/how-to-install-java-in-ubuntu/">install JDK in Ubuntu</a>, and <a target="_blank" href="https://www.freecodecamp.org/news/how-to-install-java-on-windows/">here's one that'll help you install it on Windows</a>.</p>
<p><strong>IDE Choice</strong>: Integrated Development Environments (IDEs) like Eclipse, IntelliJ IDEA, or NetBeans streamline the coding process. I personally prefer <a target="_blank" href="https://www.jetbrains.com/idea/">IntelliJ IDEA</a>, because of its intuitive interface.</p>
<h3 id="heading-start-building-the-program">Start Building the Program:</h3>
<p>Java hinges on classes. Think of them as blueprints. Our program begins with the <strong><code>HelloWorld</code></strong> class.</p>
<p>Within this class, we house the <strong><code>main</code></strong> method – Java's starting line. This is where we instruct Java to print "Hello, World!".</p>
<p>Here's what our first Java code will look like:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">HelloWorld</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        System.out.println(<span class="hljs-string">"Hello, World!"</span>);
    }
}
</code></pre>
<h3 id="heading-run-the-program">Run the Program:</h3>
<p>Using IntelliJ IDEA, save your file as <code>HelloWorld.java</code>. Hit the 'Run' button, and voilà! "Hello, World!" should appear in the output console. If you're using the command line, compile with <code>javac HelloWorld.java</code> and run with <code>java HelloWorld</code>.</p>
<p><strong>Deciphering the Code:</strong></p>
<ul>
<li><strong><code>class</code></strong>: Denotes a blueprint. <strong><code>HelloWorld</code></strong> is our chosen name.</li>
<li><strong><code>public static void main(String[] args)</code></strong>: The doorway into our program. Every Java application has one.</li>
<li><strong><code>System.out.println</code></strong>: Java's way of printing to the console. "Hello, World!" is the message we chose.</li>
</ul>
<p>Congratulations! You've penned and executed your first Java program. As you delve deeper into Java, remember this first step.</p>
<h2 id="heading-understanding-java-syntax">Understanding Java Syntax</h2>
<p>Now that we have crafted our first program, we stand on the threshold of delving into the heart of Java programming—the syntax. </p>
<p>Programming in Java is an exercise in clarity. Its syntax is a lucid framework designed not only to instruct the computer but to facilitate a deliberate and efficient dialogue with technology. </p>
<p>As we embark on this journey of understanding Java's syntax, remember it's more than memorizing rules – it's about mastering the art of clear and purposeful communication with the digital world.</p>
<h3 id="heading-objects-and-classes-in-java">Objects and Classes in Java</h3>
<p>Visualize a cat. In Java, a class like <code>Cat</code> serves as a blueprint for creating objects —a template that defines the state and behavior bound to specific data. </p>
<p>For example, when we instantiate a new Cat object using <code>Cat tabby = new Cat();</code>, we bring an instance of the <code>Cat</code> class into memory, complete with attributes such as <code>color</code> and <code>mood</code>, which describe the state of the cat, and methods like <code>purr()</code>, which is an action the cat can perform. </p>
<p>Encapsulation is at play here, encapsulating the cat's properties and the actions it can perform within one cohesive unit.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span> </span>{
    String color;
    String mood;

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">purr</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Cat purrs"</span>);
    }
}
</code></pre>
<p>Constructors are specialized methods invoked at the time of object creation to initialize new objects. Java also utilizes access modifiers like <code>public</code>, <code>private</code>, and others to define the accessibility of class members, which play a crucial role in object interaction and encapsulation. </p>
<p>The <code>new</code> keyword is vital as it allocates memory for new <code>Cat</code> instances. Through methods, these objects can interact, influence one another, and collaborate to form complex systems.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span> </span>{
    <span class="hljs-comment">// Using 'private' to restrict access to the properties from outside this class</span>
    <span class="hljs-keyword">private</span> String color;
    <span class="hljs-keyword">private</span> String mood;

    <span class="hljs-comment">// Public constructor for Cat class</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Cat</span><span class="hljs-params">(String color, String mood)</span> </span>{
        <span class="hljs-comment">// The 'this' keyword refers to the current instance of the class</span>
        <span class="hljs-keyword">this</span>.color = color;
        <span class="hljs-keyword">this</span>.mood = mood;
    }

    <span class="hljs-comment">// Public method to access the private color field</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getColor</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> color;
    }

    <span class="hljs-comment">// Public method to access the private mood field</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getMood</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> mood;
    }

    <span class="hljs-comment">// Private method, only accessible within this class</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">changeMood</span><span class="hljs-params">(String newMood)</span> </span>{
        mood = newMood;
    }

    <span class="hljs-comment">// Public method to expose the behavior of the Cat object</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">purr</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Cat purrs"</span>);
    }

    <span class="hljs-comment">// Public method to interact with the private changeMood method</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">makeHappy</span><span class="hljs-params">()</span> </span>{
        changeMood(<span class="hljs-string">"happy"</span>);
        purr(); <span class="hljs-comment">// The cat purrs when made happy</span>
    }
}

<span class="hljs-comment">// To use the class, you would create an instance of Cat using the new keyword</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Creating a new Cat object with the 'new' keyword and the constructor</span>
        Cat myCat = <span class="hljs-keyword">new</span> Cat(<span class="hljs-string">"black"</span>, <span class="hljs-string">"sleepy"</span>);

        <span class="hljs-comment">// Accessing the public methods of the Cat class</span>
        System.out.println(<span class="hljs-string">"The cat is "</span> + myCat.getColor() + <span class="hljs-string">" and feels "</span> + myCat.getMood());
        myCat.makeHappy(); <span class="hljs-comment">// Makes the cat happy which internally changes its mood and makes it purr</span>
    }
}
</code></pre>
<p>In Java, constructors are crucial for initializing new objects, as demonstrated by the <code>Cat</code> class's public constructor <code>Cat(String color, String mood)</code>. It's used to set the private fields <code>color</code> and <code>mood</code>. </p>
<p>These private fields encapsulate the state of a <code>Cat</code> object, ensuring controlled access through public methods like <code>getColor()</code> and <code>getMood()</code>. The <code>new</code> keyword is instrumental in this process, allocating memory for new instances. While the <code>changeMood()</code> method remains private for internal class use, the <code>purr()</code> method is public, allowing interaction with the cat's behavior. </p>
<p>By instantiating a new <code>Cat</code> object in the <code>Main</code> class, we demonstrate how objects are created and showcase the interplay of access modifiers that safeguard encapsulation and enable object collaboration within complex systems.</p>
<h3 id="heading-methods-in-java">Methods in Java</h3>
<p>Methods in Java are the actionable souls of objects. They define specific tasks that objects can perform. </p>
<p>In the <code>Cat</code> class shown, <code>void meow()</code> and <code>void scratch()</code> are method signatures, where <code>void</code> indicates they don't return any value, and the names <code>meow</code> and <code>scratch</code> are the actions they perform. Parentheses following the method names indicate the potential to accept inputs, which these particular methods do not require.</p>
<p>To activate a method, we call it on an object, like <code>tabby.meow();</code>, where <code>tabby</code> is the instance of the <code>Cat</code> class and <code>meow()</code> is the method being invoked. </p>
<p>Methods can encapsulate behaviors, allowing an object like <code>tabby</code> to exhibit actions such as meowing or scratching, and they can be reused to perform these actions multiple times. </p>
<p>This modularity not only promotes reusability but also helps maintain the integrity of an object's internal state, a cornerstone of encapsulation in object-oriented programming.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span> </span>{

    <span class="hljs-comment">// A method with no return value (void) that represents the cat's action of meowing</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">meow</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Prints "Meow!" to the console when the method is called</span>
        System.out.println(<span class="hljs-string">"Meow!"</span>);
    }

    <span class="hljs-comment">// A method with no return value (void) that represents the cat's action of scratching</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">scratch</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Prints "Scratch!" to the console when the method is called</span>
        System.out.println(<span class="hljs-string">"Scratch!"</span>);
    }

    <span class="hljs-comment">// Example of a method that changes the internal state of the object</span>
    <span class="hljs-comment">// Here, we assume a mood property is part of the Cat class</span>
    <span class="hljs-function"><span class="hljs-keyword">private</span> <span class="hljs-keyword">void</span> <span class="hljs-title">changeMood</span><span class="hljs-params">(String mood)</span> </span>{
        <span class="hljs-comment">// This method is private and cannot be called from outside the Cat class</span>
    }

    <span class="hljs-comment">// Additional method to demonstrate calling other methods and reusability</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">displayBehavior</span><span class="hljs-params">()</span> </span>{
        meow();  <span class="hljs-comment">// The cat meows</span>
        scratch(); <span class="hljs-comment">// The cat scratches</span>
        changeMood(<span class="hljs-string">"curious"</span>); <span class="hljs-comment">// The cat's mood is changed internally</span>
    }
}

<span class="hljs-comment">// Class containing the main method to run the program</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Creating a new Cat object using the 'new' keyword</span>
        Cat tabby = <span class="hljs-keyword">new</span> Cat();

        <span class="hljs-comment">// Calling the public methods of the Cat class</span>
        tabby.meow(); <span class="hljs-comment">// Output: Meow!</span>
        tabby.scratch(); <span class="hljs-comment">// Output: Scratch!</span>

        <span class="hljs-comment">// Demonstrating the reusability of methods</span>
        tabby.displayBehavior(); <span class="hljs-comment">// Calls multiple methods to display behaviors</span>
    }
}
</code></pre>
<h3 id="heading-instance-variables-in-java">Instance Variables in Java</h3>
<p>Instance variables capture the essence of an object's state within a Java class. In the example of a <code>Cat</code> class, the properties <code>name</code> and <code>age</code> are specific to each <code>Cat</code> object, giving each a unique identity.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span> </span>{
    <span class="hljs-comment">// Private instance variables, encapsulating the state of the Cat object</span>
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;

    <span class="hljs-comment">// Constructor that initializes a Cat object with a given name and age</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Cat</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
    }

    <span class="hljs-comment">// Public getter for the name, allowing read access to the private variable</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.name;
    }

    <span class="hljs-comment">// Public setter for the name, allowing write access to the private variable</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setName</span><span class="hljs-params">(String name)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
    }

    <span class="hljs-comment">// Public getter for the age, allowing read access to the private variable</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">this</span>.age;
    }

    <span class="hljs-comment">// Public setter for the age, allowing write access to the private variable</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAge</span><span class="hljs-params">(<span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.age = age;
    }

    <span class="hljs-comment">// Public method to display the Cat's attributes</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">displayInfo</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-keyword">this</span>.name + <span class="hljs-string">" is "</span> + <span class="hljs-keyword">this</span>.age + <span class="hljs-string">" year(s) old."</span>);
    }
}
</code></pre>
<p>Here, encapsulation is employed by making the <code>name</code> and <code>age</code> variables private, which means they cannot be accessed directly from outside the class. Instead, public getters and setters (<code>getName()</code>, <code>setName(String name)</code>, <code>getAge()</code>, and <code>setAge(int age)</code>) are provided to interact with these properties safely. </p>
<p>This approach not only protects the data from being changed in unintended ways but also enables a controlled interface for other classes to interact with the <code>Cat</code> objects.</p>
<h3 id="heading-java-basic-syntax-rules">Java Basic Syntax Rules</h3>
<p>Java's syntax forms the foundation of its programming structure:</p>
<pre><code class="lang-java"><span class="hljs-comment">// The 'public' modifier allows this class to be accessed from other classes.</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
    <span class="hljs-comment">// 'main' method: Java starts executing the program from this method.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// ... your code goes here</span>
    }
}
</code></pre>
<p>When crafting a Java class:</p>
<ol>
<li><strong>Class Declaration</strong>: The <code>public</code> keyword specifies that the class is accessible from anywhere in the program, promoting a modular and interactive coding environment.</li>
<li><strong>The <code>main</code> Method</strong>: This is where the program's execution commences. It must be <code>public</code> to be universally invokable, <code>static</code> to be callable without instantiating the class, and <code>void</code> to indicate it doesn't return any value. The <code>String[] args</code> parameter serves as a container for any command-line arguments that may be passed to the program.</li>
<li><strong>File Name</strong>: The name of the source file should precisely match the class name (<code>MyClass</code> in this case) and should have the <code>.java</code> extension (hence <code>MyClass.java</code>), which is essential for the Java compiler to recognize and compile the class correctly.</li>
</ol>
<p>By adhering to these basic syntax rules, you ensure that your Java program is structured correctly and ready for execution. These guidelines lay the groundwork for developing clean, efficient, and well-functioning Java applications.</p>
<h2 id="heading-chapter-2-java-data-types-and-variables">Chapter 2: Java Data Types and Variables</h2>
<p>Building on the basics of your first Java program and syntax understanding, we can now delve into Data Types and Variables. Mastering these is crucial for managing data efficiently — <code>int</code> and <code>boolean</code> for direct value handling, <code>String</code> for complex structures, and arrays and enums for structured collections and constant values. </p>
<h3 id="heading-overview-of-the-eight-primitive-data-types">Overview of the Eight Primitive Data Types:</h3>
<p>Each data type, crafted for a specific purpose, brings its own flavor to the Java programming language. </p>
<p><code>int</code> – a commonly used type for whole numbers:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> score = <span class="hljs-number">100</span>;
</code></pre>
<p><code>byte</code> – a compact data type, great for conserving memory:</p>
<pre><code class="lang-java"><span class="hljs-keyword">byte</span> age = <span class="hljs-number">27</span>;
</code></pre>
<p><code>short</code>  – a tad larger than <code>byte</code> but smaller than <code>int</code>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">short</span> year = <span class="hljs-number">2023</span>;
</code></pre>
<p><code>long</code> – for representing vast numbers:</p>
<pre><code class="lang-java"><span class="hljs-keyword">long</span> population = <span class="hljs-number">7816253000L</span>;
</code></pre>
<p><code>float</code> – floating-point numbers with single precision:</p>
<pre><code class="lang-java"><span class="hljs-keyword">float</span> price = <span class="hljs-number">10.99F</span>;
</code></pre>
<p><code>double</code> – floating-point numbers with double precision:</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> distance = <span class="hljs-number">384.4</span>;
</code></pre>
<p><code>boolean</code> – the epitome of simplicity, true or false:</p>
<pre><code>boolean isJavaFun = <span class="hljs-literal">true</span>;
</code></pre><p><code>char</code> – encapsulates single characters:</p>
<pre><code class="lang-java"><span class="hljs-keyword">char</span> initial = <span class="hljs-string">'J'</span>;
</code></pre>
<h3 id="heading-storage-size-minimum-and-maximum-values-and-examples">Storage Size, Minimum and Maximum Values, and Examples</h3>
<p>Each primitive type occupies a certain space in memory, ranging from <code>byte</code>'s modest 8 bits to <code>long</code> and <code>double</code>'s chunky 64 bits. </p>
<p>Likewise, they each have their own range of representable values. For instance, an <code>int</code> can stretch from <code>-2^31</code> to <code>2^31-1</code>, and a <code>char</code>, in its 16-bit purity, can represent Unicode characters.</p>
<h4 id="heading-overflow-and-underflow">Overflow and Underflow</h4>
<p>Ever tried adding 1 to the maximum value an <strong><code>int</code></strong> can hold? Or subtracting 1 from its minimum value? These actions will result in overflow and underflow, respectively. While these might sound catastrophic, in Java, it usually just wraps the number around.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> maxValue = Integer.MAX_VALUE;
<span class="hljs-keyword">int</span> overflow = maxValue + <span class="hljs-number">1</span>;
</code></pre>
<p>The world of primitive data types in Java is far from mundane — it's the terrain where we first set our feet, grounding our understanding. From the basics of a <strong><code>boolean</code></strong> to the vastness of a <strong><code>long</code></strong>, these data types represent the core of Java's ability to interact with information.</p>
<h3 id="heading-non-primitive-data-types">Non-primitive data types</h3>
<p>As we build on our understanding of primitive types, we now need to delve deeper into non-primitive data types, as they form the bedrock of object-oriented programming in Java.</p>
<p>In software development, precision and the right tool selection are paramount. Java's non-primitive data types serve as essential tools, granting programmers the flexibility to define their own data types, store multiple data items, and harness the power of method invocations. We covered this in the Java Syntax section, but lets briefly touch upon it again.</p>
<h4 id="heading-types-of-non-primitive-data-types">Types of Non-Primitive Data Types:</h4>
<p><strong>Class:</strong> Think of a class as the blueprint of a building. Just as a building comprises various sections like rooms, corridors, and lobbies, a class consists of properties and methods. It's identifiable by its name and can inherit attributes and behaviors from another class, termed as a superclass.</p>
<p>Example of a class:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Demo</span> </span>{
    <span class="hljs-keyword">int</span> a, b;

    <span class="hljs-comment">// Constructor</span>
    Demo(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b) {
        <span class="hljs-keyword">this</span>.a = a;
        <span class="hljs-keyword">this</span>.b = b;
    }

    <span class="hljs-comment">// Method to add two numbers</span>
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">addition</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> a + b;
    }

    <span class="hljs-comment">// Method to subtract two numbers</span>
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">subtraction</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> a - b;
    }
}
</code></pre>
<p><strong>String:</strong> A fundamental component in Java, the String class facilitates the creation and manipulation of a sequence of characters. It's distinct from some other languages in that you don't need to use a terminating null character.</p>
<p>Example of a string:</p>
<pre><code class="lang-java">String s1 = <span class="hljs-string">"Scaler"</span>;
String s2 = <span class="hljs-keyword">new</span> String(<span class="hljs-string">"Academy"</span>);
</code></pre>
<p><strong>Array:</strong> If we analogize an array to a bookshelf, each slot (or index) in an array holds a specific element (or value). Crucially, every element on that particular shelf (or array) is of the same data type.</p>
<p>Example of an array:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span>[] arr1 = {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>};
<span class="hljs-keyword">double</span>[] arr2 = {<span class="hljs-number">1.1</span>, <span class="hljs-number">2.2</span>, <span class="hljs-number">3.3</span>};
</code></pre>
<p><strong>Interface:</strong> Interfaces in Java act as a contract. They outline a set of methods without specifying their implementations. Classes that decide to "sign" this contract (that is implement the interface) are bound to provide implementations for all its methods.</p>
<p>Example of an interface:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Operations</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">addition</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">subtraction</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Solve</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Operations</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">addition</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>{
        <span class="hljs-keyword">return</span> a + b;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">subtraction</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>{
        <span class="hljs-keyword">return</span> a - b;
    }
}
</code></pre>
<h4 id="heading-difference-between-primitive-and-non-primitive-data-types">Difference between Primitive and Non-Primitive Data Types:</h4>
<ul>
<li><strong>Origin:</strong> Primitive types are innately defined in Java. On the contrary, non-primitive types are predominantly user-defined, with notable exceptions such as the String.</li>
<li><strong>Value Storage:</strong> Primitive data types are designed to hold a single value. In contrast, non-primitive types can encompass multiple values or even complex behaviors.</li>
<li><strong>Memory Allocation:</strong> Primitive types are allocated memory on the stack. However, for non-primitive types, the stack merely contains a reference, while the actual object resides in the heap memory.</li>
</ul>
<h3 id="heading-type-casting">Type casting</h3>
<p>Typcasting (translating one data type to another) is an integral concept in software development. You can use it to convert one type of information to another type, either explicitly (something you do yourself) or implicitly (via compiler compilation). </p>
<p>Understanding type casting is essential to writing efficient code as it impacts both program functionality and resource utilization.</p>
<h4 id="heading-what-is-type-casting">What is Type Casting?</h4>
<p>Type casting refers to the practice of changing one data type entity to another. You could think of type casting like trying to fit a square peg into a circular hole: sometimes you will need to reshape its form before fitting. </p>
<p>Also, as various sections interact within programs and compatibility issues become an issue between these components of code, type casting becomes necessary for compatibility purposes.</p>
<h4 id="heading-implicit-casting-automatic">Implicit Casting (Automatic):</h4>
<p>When the conversion is risk-free and the destination type can hold the original data without loss, the compiler steps in, handling it automatically.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> myInt = <span class="hljs-number">9</span>;
<span class="hljs-keyword">double</span> myDouble = myInt;  <span class="hljs-comment">// Implicit casting from int to double</span>
</code></pre>
<p>Here, an <strong><code>int</code></strong> value fits comfortably into a <strong><code>double</code></strong>, so no explicit command is needed.</p>
<h4 id="heading-explicit-casting-manual">Explicit Casting (Manual):</h4>
<p>At times, the conversion might be risky, potentially leading to data loss. Here, developers must step in, indicating the casting manually.</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> myDouble = <span class="hljs-number">9.78</span>;
<span class="hljs-keyword">int</span> myInt = (<span class="hljs-keyword">int</span>) myDouble;  <span class="hljs-comment">// Explicit casting from double to int</span>
</code></pre>
<p>Note that 9.78 becomes 9, and the decimal portion (.78) is discarded. This is where potential data loss lurks.</p>
<h4 id="heading-type-casting-in-object-oriented-programming">Type Casting in Object-Oriented Programming</h4>
<p>In OOP, casting isn't just a data play – it extends to objects and their types.</p>
<p><strong>Upcasting</strong>: It's like looking at an object through a broader lens. A specific object (like a <strong><code>Dog</code></strong>) is viewed as a more general object (like an <strong><code>Animal</code></strong>). It's always safe.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{}
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span> </span>{}
}

Animal myDog = <span class="hljs-keyword">new</span> Dog();  <span class="hljs-comment">// Upcasting the Dog object to Animal type</span>
</code></pre>
<p><strong>Downcasting</strong>: This is a tad riskier. It's about viewing a general object through a specific lens. Explicit casting is needed since there's an inherent risk.</p>
<pre><code class="lang-java">Dog myNewDog = (Dog) myDog;  <span class="hljs-comment">// Downcasting the Animal object to Dog type</span>
</code></pre>
<p><strong>Checking Object Type</strong>: Before embarking on downcasting, it's wise to check the type to avoid runtime errors.</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span>(myDog <span class="hljs-keyword">instanceof</span> Dog) {
    Dog anotherDog = (Dog) myDog;
}
</code></pre>
<h4 id="heading-best-practices-in-type-casting">Best Practices in Type Casting</h4>
<p><strong>Caution Over Casting</strong>: Not every situation requires casting. Only use it when necessary. Indiscriminate casting can make your code harder to read and maintain.</p>
<p><strong>Stay Vigilant</strong>: Always be on the lookout for potential data loss. For instance, when casting float to int, remember the decimal truncation.</p>
<p><strong>Exception Handling</strong>: Anticipate exceptions that might arise, like <strong><code>ClassCastException</code></strong>. When they do, handle them gracefully to ensure your program doesn't crash unexpectedly.</p>
<pre><code class="lang-java"><span class="hljs-keyword">try</span> {
    Dog retrievedDog = (Dog) someAnimal;
} <span class="hljs-keyword">catch</span> (ClassCastException e) {
    System.out.println(<span class="hljs-string">"Failed to cast the object."</span>);
}
</code></pre>
<h4 id="heading-common-pitfalls-and-how-to-avoid-them">Common Pitfalls and How to Avoid Them</h4>
<p><strong>Loss of Precision</strong>: Remember, casting a float or double to an int truncates the decimal. Always ensure that's the desired behavior.</p>
<pre><code class="lang-java"><span class="hljs-keyword">float</span> value = <span class="hljs-number">3.14f</span>;
<span class="hljs-keyword">int</span> intValue = (<span class="hljs-keyword">int</span>) value;  <span class="hljs-comment">// intValue will be 3</span>
</code></pre>
<p><strong>Overflows &amp; Underflows</strong>: Casting might lead to unexpected results if the value doesn't fit into the destination type.</p>
<pre><code class="lang-java"><span class="hljs-keyword">long</span> bigNumber = <span class="hljs-number">5000000000L</span>;
<span class="hljs-keyword">int</span> smallerNumber = (<span class="hljs-keyword">int</span>) bigNumber;  <span class="hljs-comment">// Potential for unexpected values</span>
</code></pre>
<p><strong>ClassCastException</strong>: Particularly in OOP languages, always check object types before attempting to downcast.</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (someAnimal <span class="hljs-keyword">instanceof</span> Dog) {
    Dog d = (Dog) someAnimal;
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"Can't cast this animal to a Dog."</span>);
}
</code></pre>
<h2 id="heading-chapter-3-java-operators-and-control-statements">Chapter 3: Java Operators and Control Statements</h2>
<p>Building on the basics of Java we covered in Chapters 1 and 2, we'll now move to the critical components of Chapter 3: Operators and Control Statements. </p>
<p>Operators are vital, engaged in over 70% of code logic decisions, while control statements dictate the flow, essential in around 85% of Java applications. </p>
<p>This chapter will explore the pivotal role these elements play in crafting algorithms and object-oriented programs, ensuring you can create well-structured and effective Java code.</p>
<h3 id="heading-arithmetic-operators">Arithmetic operators</h3>
<p>At the heart of most programming tasks are operators. They dictate the flow and logic within algorithms, helping computers make decisions, process data, and deliver results. </p>
<p>Specifically, arithmetic operators are foundational pillars that offer essential functionalities, allowing us to execute complex operations seamlessly. These tools, although ubiquitous, sometimes go unnoticed in their daily use. Yet, their understanding is vital for anyone aspiring to code proficiently.</p>
<h4 id="heading-basic-arithmetic-operators">Basic Arithmetic Operators</h4>
<p><strong>Addition (+)</strong>: More than a mere counting mechanism, the addition operator is indispensable in aggregation tasks. Whether you're summing up totals or calculating a grand sum, <strong><code>+</code></strong> remains at the core.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> sum = <span class="hljs-number">3</span> + <span class="hljs-number">4</span>;  <span class="hljs-comment">// sum holds value 7</span>
</code></pre>
<p><strong>Subtraction (-)</strong>: An unsung hero when it comes to pinpointing differences or making alterations. It can be vital when budgeting, calculating time differences, or even tracking inventory changes.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> diff = <span class="hljs-number">10</span> - <span class="hljs-number">3</span>;  <span class="hljs-comment">// diff holds value 7</span>
</code></pre>
<p><strong>Multiplication (*)</strong>: While it can represent repeated addition, its true prowess lies in scaling and proportionate increase. From calculating areas to understanding growth, multiplication is pivotal.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> product = <span class="hljs-number">7</span> * <span class="hljs-number">3</span>;  <span class="hljs-comment">// product is 21</span>
</code></pre>
<p><strong>Division (/)</strong>: A tool often used to partition values. Whether distributing resources, calculating ratios, or determining average values, division serves as a crucial operation.</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> quotient = <span class="hljs-number">20.0</span> / <span class="hljs-number">3</span>;  <span class="hljs-comment">// quotient is approximately 6.67</span>
</code></pre>
<p><strong>Modulus (%)</strong>: Moving past just division, modulus allows for the understanding of remainders. It's paramount in cyclical operations and certain algorithms like those dealing with circular arrays.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> remainder = <span class="hljs-number">7</span> % <span class="hljs-number">3</span>;  <span class="hljs-comment">// remainder is 1</span>
</code></pre>
<h4 id="heading-unary-operators">Unary Operators</h4>
<ul>
<li><strong>Increment (++)</strong>: A succinct way to enhance a value. It's particularly beneficial in loop counters and iterative processes.</li>
<li><strong>Prefix</strong>: By using <strong><code>++a</code></strong>, the value of 'a' is increased before the current operation gets executed.</li>
<li><strong>Postfix</strong>: With <strong><code>a++</code></strong>, the current operation utilizes 'a' before increasing its value.</li>
<li><strong>Decrement (--)</strong>: Serving as the inverse of increment, it methodically diminishes a value, commonly used in reverse iterations and counters.</li>
<li>As with increment, prefix and postfix nuances apply to the decrement operator as well.</li>
</ul>
<h4 id="heading-compound-assignment-operators">Compound Assignment Operators</h4>
<p>These operators infuse arithmetic operations with assignment. They offer concise code, improving its readability while ensuring efficiency.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> x = <span class="hljs-number">10</span>;
x += <span class="hljs-number">5</span>;  <span class="hljs-comment">// An elegant way of saying x = x + 5; x now holds 15</span>
</code></pre>
<h4 id="heading-the-importance-of-data-types">The Importance of Data Types</h4>
<p>The behavior of arithmetic operations can vary depending on the data types employed.</p>
<p><strong>Floating-point arithmetic</strong>: While it affords precision, you need to remain vigilant about rounding errors or floating-point anomalies.</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> result = <span class="hljs-number">10.0</span> / <span class="hljs-number">3</span>;  <span class="hljs-comment">// result holds 3.3333...</span>
</code></pre>
<p><strong>Integer arithmetic</strong>: It delivers whole numbers, eschewing any decimal fractions. Ideal for countable entities but can lead to unintended truncations.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> resultInt = <span class="hljs-number">10</span> / <span class="hljs-number">3</span>;  <span class="hljs-comment">// resultInt holds 3, the fraction is discarded</span>
</code></pre>
<p>Be wary of integer divisions, ensuring that you choose the correct data type based on the computational context.</p>
<h4 id="heading-type-promotion-in-expressions">Type Promotion in Expressions</h4>
<p>Java strives to avoid accidental data loss by promoting data types in mixed-type operations. For example, an operation involving an <code>int</code> and a <code>double</code> will convert the <code>int</code> to a <code>double</code> to ensure a uniform type for accurate computation.</p>
<h4 id="heading-mathematical-methods-amp-classes">Mathematical Methods &amp; Classes</h4>
<p>Java’s <code>Math</code> class is a reservoir of handy mathematical utilities.</p>
<p><code>Math.pow(a, b)</code> efficiently computes 'a' raised to the power of 'b'.</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> eight = Math.pow(<span class="hljs-number">2</span>, <span class="hljs-number">3</span>);  <span class="hljs-comment">// eight holds 8.0</span>
</code></pre>
<p><code>Math.sqrt(x)</code> returns the square root of 'x', a common function in distance calculations and quadratic algorithms.</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> squareRoot = Math.sqrt(<span class="hljs-number">64</span>);  <span class="hljs-comment">// squareRoot holds 8.0</span>
</code></pre>
<p>These methods magnify Java's computational prowess, taking away the need for manually crafting these algorithms.</p>
<h4 id="heading-practical-scenarios-amp-examples">Practical Scenarios &amp; Examples</h4>
<p>For instance, consider you're managing a shop and need to calculate the total cost after adding a service charge:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> totalCost = <span class="hljs-number">50</span>;
totalCost += <span class="hljs-number">25</span>;  <span class="hljs-comment">// Compound assignment, totalCost is now 75</span>
</code></pre>
<p>Or, perhaps you're developing a geometry application and need to calculate the diagonal length of a square:</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> sideLength = <span class="hljs-number">8.0</span>;
<span class="hljs-keyword">double</span> diagonal = sideLength * Math.sqrt(<span class="hljs-number">2</span>);  <span class="hljs-comment">// Using Math class for square root</span>
</code></pre>
<h3 id="heading-relational-operators">Relational operators</h3>
<p>Relational operators, also known as comparison operators, serve as the cornerstone in the world of decision-making for developers. They pave the way for crafting conditional statements, driving loops, and orchestrating the flow in algorithms by determining the truth value of specific conditions.</p>
<p>Java boasts a collection of relational operators that serve the purpose of comparing two values. At their core, these operators yield a boolean outcome – either <code>true</code> or <code>false</code>:</p>
<p><strong>Equality (==)</strong>: This operator states whether two values share parity.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> a = <span class="hljs-number">5</span>;
<span class="hljs-keyword">boolean</span> result = (a == <span class="hljs-number">5</span>);  <span class="hljs-comment">// The outcome stored in 'result' is true</span>
</code></pre>
<p><strong>Inequality (!=)</strong>: As the counter to equality, it checks if two values aren't the same.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> b = <span class="hljs-number">7</span>;
<span class="hljs-keyword">boolean</span> result = (b != <span class="hljs-number">5</span>);  <span class="hljs-comment">// Here, 'result' is true since 7 isn't 5</span>
</code></pre>
<p><strong>Greater Than (&gt;)</strong>: It evaluates if the value on the left is greater than the one on the right.</p>
<pre><code class="lang-java"><span class="hljs-keyword">boolean</span> check = (<span class="hljs-number">10</span> &gt; <span class="hljs-number">3</span>);  <span class="hljs-comment">// 'check' is true, 10 does surpass 3</span>
</code></pre>
<p><strong>Less Than (&lt;)</strong>: This operator checks if the value on the left is smaller than the one on the right.</p>
<pre><code class="lang-java"><span class="hljs-keyword">boolean</span> check = (<span class="hljs-number">2</span> &lt; <span class="hljs-number">8</span>);  <span class="hljs-comment">// As expected, 'check' is true here</span>
</code></pre>
<p><strong>Greater Than or Equal to (&gt;=)</strong>: A dual-purpose operator, it confirms if the left value either is greater than or equal to the right.</p>
<pre><code class="lang-java"><span class="hljs-keyword">boolean</span> equalityOrGreater = (<span class="hljs-number">7</span> &gt;= <span class="hljs-number">7</span>);  <span class="hljs-comment">// This yields true since 7 equals 7</span>
</code></pre>
<p><strong>Less Than or Equal to (&lt;=)</strong>: Similarly dual-purposed, it verifies if the left value is less than or equal to the right.</p>
<pre><code class="lang-java"><span class="hljs-keyword">boolean</span> equalityOrLess = (<span class="hljs-number">4</span> &lt;= <span class="hljs-number">5</span>);  <span class="hljs-comment">// 'equalityOrLess' will store true</span>
</code></pre>
<h4 id="heading-relational-operators-and-object-references">Relational Operators and Object References</h4>
<p>Distinguishing between primitive data types and objects is vital in Java, especially when employing the <code>==</code> operator.</p>
<p>With primitive data types, <code>==</code> straightforwardly checks whether values are equal.</p>
<p>For objects, the <code>==</code> operator delves deeper, determining if both references point to an identical memory location. It doesn't evaluate content equality. Instead, you'll use the <code>equals()</code> method for that purpose.</p>
<pre><code class="lang-java">String str1 = <span class="hljs-keyword">new</span> String(<span class="hljs-string">"Hello"</span>);
String str2 = <span class="hljs-keyword">new</span> String(<span class="hljs-string">"Hello"</span>);
<span class="hljs-keyword">boolean</span> refCheck = (str1 == str2);       <span class="hljs-comment">// This returns false; distinct memory locations</span>
<span class="hljs-keyword">boolean</span> contentCheck = str1.equals(str2);  <span class="hljs-comment">// True here since the content is identical</span>
</code></pre>
<h4 id="heading-chaining-relational-operators">Chaining Relational Operators</h4>
<p>Using various relational and logical operators together can produce intricate conditions:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> age = <span class="hljs-number">25</span>;
<span class="hljs-keyword">boolean</span> isAdult = (age &gt;= <span class="hljs-number">18</span> &amp;&amp; age &lt;= <span class="hljs-number">65</span>);  <span class="hljs-comment">// 'isAdult' stands true for ages 18 through 65</span>
</code></pre>
<p>But there are some potential pitfalls you should be aware of:</p>
<p><strong>Floating-point Comparisons</strong>: Precision errors can distort direct floating-point comparisons using relational operators. To sidestep this, consider comparing the absolute difference against a minuscule threshold.</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> result = <span class="hljs-number">0.1</span> + <span class="hljs-number">0.2</span>;
<span class="hljs-keyword">boolean</span> isEqual = (result == <span class="hljs-number">0.3</span>);  <span class="hljs-comment">// False here due to precision glitches</span>
<span class="hljs-keyword">boolean</span> isNearlyEqual = Math.abs(result - <span class="hljs-number">0.3</span>) &lt; <span class="hljs-number">0.000001</span>;  <span class="hljs-comment">// True since the difference is minuscule</span>
</code></pre>
<p><strong>Auto-boxing Hazards</strong>: The quirk of auto-boxing in Java can spawn unexpected results when comparing wrapper objects:</p>
<pre><code class="lang-java">Integer num1 = <span class="hljs-number">127</span>;
Integer num2 = <span class="hljs-number">127</span>;
<span class="hljs-keyword">boolean</span> check1 = (num1 == num2);  <span class="hljs-comment">// True here due to integer caching within the range of -128 to 127</span>
Integer num3 = <span class="hljs-number">200</span>;
Integer num4 = <span class="hljs-number">200</span>;
<span class="hljs-keyword">boolean</span> check2 = (num3 == num4);  <span class="hljs-comment">// This turns out false; they're different references</span>
</code></pre>
<p>Practical scenarios and applications:</p>
<ul>
<li><strong>Sorting Algorithms</strong>: Algorithms like Bubble Sort or Quick Sort lean on relational operators to determine the sequential order of elements.</li>
<li><strong>Decision-making in Applications</strong>: If an application is evaluating loan eligibility predicated on age and income, or sifting data in accordance with user specifications, you'll find relational operators at work.</li>
<li><strong>Gaming</strong>: Be it adjudging victors based on score metrics or launching events post certain milestones, relational operators sculpt the gaming narrative.</li>
</ul>
<h4 id="heading-exercises-amp-challenges">Exercises &amp; Challenges</h4>
<ul>
<li><strong>Basic Exercises</strong>: Task yourself with architecting conditions that sort grades (A, B, C, and so forth) anchored on scored marks.</li>
<li><strong>Intermediate Challenges</strong>: Take a stab at designing a rudimentary high-score tracker for any game.</li>
<li><strong>Advanced Puzzles</strong>: Venture into implementing the binary search algorithm. It predominantly hinges on relational operators to pinpoint elements.</li>
</ul>
<p>An Advanced Program: Efficient Filtering System:</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FilterSystem</span> </span>{

    <span class="hljs-comment">// Mock database entries</span>
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">final</span> String[] DATABASE = {
        <span class="hljs-string">"Product A: Price $100, Category Electronics"</span>,
        <span class="hljs-string">"Product B: Price $50, Category Books"</span>,
        <span class="hljs-string">"Product C: Price $150, Category Electronics"</span>,
        <span class="hljs-string">"Product D: Price $30, Category Apparel"</span>,
        <span class="hljs-comment">// ... more entries</span>
    };

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">filterByPriceRange</span><span class="hljs-params">(<span class="hljs-keyword">int</span> min, <span class="hljs-keyword">int</span> max)</span> </span>{
        <span class="hljs-keyword">for</span> (String entry : DATABASE) {
            String[] splitEntry = entry.split(<span class="hljs-string">" "</span>);
            <span class="hljs-keyword">int</span> price = Integer.parseInt(splitEntry[<span class="hljs-number">3</span>].substring(<span class="hljs-number">1</span>));  <span class="hljs-comment">// Extract price</span>
            <span class="hljs-keyword">if</span> (price &gt;= min &amp;&amp; price &lt;= max) {
                System.out.println(entry);
            }
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        filterByPriceRange(<span class="hljs-number">50</span>, <span class="hljs-number">150</span>);  <span class="hljs-comment">// Filters entries with prices between $50 and $150</span>
    }
}
</code></pre>
<h3 id="heading-logical-operators">Logical operators</h3>
<p>Before diving deeper into object oriented programming, it's important to understand logical operators. They serve as tools for establishing truth values of expressions. And combined with relational operators they allow more complex conditions to be created.</p>
<h4 id="heading-fundamental-logical-operators">Fundamental Logical Operators</h4>
<p>Java offers a suite of logical operators to help you evaluate and combine boolean expressions:</p>
<ul>
<li><strong>Logical AND (&amp;&amp;)</strong>: Returns true if both operands are true.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">boolean</span> result = (<span class="hljs-number">5</span> &gt; <span class="hljs-number">3</span>) &amp;&amp; (<span class="hljs-number">7</span> &lt; <span class="hljs-number">10</span>);  <span class="hljs-comment">// result is true</span>
</code></pre>
<ul>
<li><strong>Logical OR (||)</strong>: Returns true if at least one of the operands is true.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">boolean</span> result = (<span class="hljs-number">5</span> &lt; <span class="hljs-number">3</span>) || (<span class="hljs-number">7</span> &lt; <span class="hljs-number">10</span>);  <span class="hljs-comment">// result is true</span>
</code></pre>
<ul>
<li><strong>Logical NOT (!)</strong>: Inverts the truth value of the operand.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">boolean</span> result = !(<span class="hljs-number">5</span> &gt; <span class="hljs-number">3</span>);  <span class="hljs-comment">// result is fals</span>
</code></pre>
<h4 id="heading-short-circuit-behavior-in-java">Short-Circuit Behavior in Java</h4>
<p>Java supports <strong>short-circuit evaluation</strong> for its logical operators. This means:</p>
<ul>
<li>For <code>&amp;&amp;</code>, if the left operand is <code>false</code>, the right operand is not evaluated.</li>
<li>For <code>||</code>, if the left operand is <code>true</code>, the right operand is not evaluated.</li>
</ul>
<p>This behavior is not only efficient but can also be useful in avoiding potential runtime errors:</p>
<pre><code class="lang-java">String str = <span class="hljs-keyword">null</span>;
<span class="hljs-keyword">if</span> (str != <span class="hljs-keyword">null</span> &amp;&amp; !str.isEmpty()) {
    System.out.println(<span class="hljs-string">"String is not empty"</span>);
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"String is empty or null"</span>);
}
</code></pre>
<p>In the above example, using the <code>&amp;&amp;</code> operator ensures that <code>str.isEmpty()</code> is only called if <code>str</code> is not <code>null</code>, avoiding a potential <code>NullPointerException</code>.</p>
<h4 id="heading-logical-operators-with-non-boolean-values">Logical Operators with Non-Boolean Values</h4>
<p>While Java's logical operators primarily work with boolean values, bitwise logical operators can be used with integers:</p>
<ul>
<li><strong>Bitwise AND (&amp;)</strong></li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> result = <span class="hljs-number">5</span> &amp; <span class="hljs-number">3</span>;  <span class="hljs-comment">// result is 1</span>
</code></pre>
<ul>
<li><strong>Bitwise OR (|)</strong></li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> result = <span class="hljs-number">5</span> | <span class="hljs-number">3</span>;  <span class="hljs-comment">// result is 7</span>
</code></pre>
<ul>
<li><strong>Bitwise XOR (^)</strong>: Returns 1 for differing bits and 0 for matching bits.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> result = <span class="hljs-number">5</span> ^ <span class="hljs-number">3</span>;  <span class="hljs-comment">// result is 6</span>
</code></pre>
<p>Remember, these operators work on the individual bits of integers.</p>
<h4 id="heading-truth-tables-deciphering-logical-operations">Truth Tables: Deciphering Logical Operations</h4>
<p>Understanding logical operations becomes more intuitive with <strong>truth tables</strong>. They map all possible truth values of inputs to their resulting outputs.</p>
<p><strong>AND (&amp;&amp;)</strong></p>
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>A &amp;&amp; B</th>
</tr>
</thead>
<tbody>
<tr>
<td>T</td>
<td>T</td>
<td>T</td>
</tr>
<tr>
<td>T</td>
<td>F</td>
<td>F</td>
</tr>
<tr>
<td>F</td>
<td>T</td>
<td>F</td>
</tr>
<tr>
<td>F</td>
<td>F</td>
<td>F</td>
</tr>
</tbody>
</table>

<p><strong>OR (||)</strong></p>
<table>
<thead>
<tr>
<th>A</th>
<th>B</th>
<th>A || B</th>
</tr>
</thead>
<tbody>
<tr>
<td>T</td>
<td>T</td>
<td>T</td>
</tr>
<tr>
<td>T</td>
<td>F</td>
<td>T</td>
</tr>
<tr>
<td>F</td>
<td>T</td>
<td>T</td>
</tr>
<tr>
<td>F</td>
<td>F</td>
<td>F</td>
</tr>
</tbody>
</table>

<p><strong>NOT (!)</strong></p>
<table>
<thead>
<tr>
<th>A</th>
<th>!A</th>
</tr>
</thead>
<tbody>
<tr>
<td>T</td>
<td>F</td>
</tr>
<tr>
<td>F</td>
<td>T</td>
</tr>
</tbody>
</table>

<h3 id="heading-practical-applications-of-logical-operators">Practical Applications of Logical Operators</h3>
<ul>
<li><strong>User Input Validation</strong>: By combining multiple conditions, you can rigorously validate user inputs.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> age = <span class="hljs-number">25</span>;
<span class="hljs-keyword">boolean</span> hasLicense = <span class="hljs-keyword">true</span>;

<span class="hljs-keyword">if</span> (age &gt;= <span class="hljs-number">18</span> &amp;&amp; hasLicense) {
    System.out.println(<span class="hljs-string">"Allowed to drive"</span>);
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"Not allowed to drive"</span>);
}
</code></pre>
<ul>
<li><strong>Game Development</strong>: Crafting game logic, like determining if a player has met all conditions to progress to the next level.</li>
<li><strong>Security</strong>: Evaluating multiple conditions to grant or deny access.</li>
</ul>
<h3 id="heading-exercises-amp-challenges-solutions">Exercises &amp; Challenges - Solutions</h3>
<p><strong>Basic Exercise:</strong></p>
<p><strong>Problem</strong>: Given three boolean variables <code>a</code>, <code>b</code>, and <code>c</code>. Determine if only one of them is true.</p>
<p><strong>Solution</strong>: The idea is to use the OR (<strong><code>||</code></strong>) operator to check if any one of the variables is true and then ensure that not more than one of them is true.</p>
<pre><code class="lang-java"><span class="hljs-keyword">boolean</span> a = ... <span class="hljs-comment">// Assign some value</span>
<span class="hljs-keyword">boolean</span> b = ... <span class="hljs-comment">// Assign some value</span>
<span class="hljs-keyword">boolean</span> c = ... <span class="hljs-comment">// Assign some value</span>

<span class="hljs-comment">// Begin the conditional check</span>
<span class="hljs-keyword">if</span> (
    <span class="hljs-comment">// The following conditions are checking each scenario where only one variable is true:</span>

    (a &amp;&amp; !b &amp;&amp; !c)  <span class="hljs-comment">// First condition: 'a' is true AND 'b' is false AND 'c' is false</span>
    || 
    (!a &amp;&amp; b &amp;&amp; !c)  <span class="hljs-comment">// Second condition: 'a' is false AND 'b' is true AND 'c' is false</span>
    || 
    (!a &amp;&amp; !b &amp;&amp; c)  <span class="hljs-comment">// Third condition: 'a' is false AND 'b' is false AND 'c' is true</span>
) {
    <span class="hljs-comment">// If any of the above conditions is met, only one of the variables is true</span>
    System.out.println(<span class="hljs-string">"Only one of the variables is true."</span>);
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// If none of the above conditions is met, either all are false, all are true, or two are true.</span>
    System.out.println(<span class="hljs-string">"Either none or more than one of the variables is true."</span>);
}
</code></pre>
<p><strong>Intermediate Challenge:</strong></p>
<p><strong>Problem</strong>: Implement a basic "AND" gate simulator using only the "NOT" and "OR" operators.</p>
<p><strong>Solution</strong>: Recall the logical identity <code>(A AND B) = NOT(NOT A OR NOT B)</code>. Using this, we can simulate an AND gate with NOT and OR operators.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Declare and initialize a boolean variable for Input A</span>
<span class="hljs-keyword">boolean</span> A = ...; <span class="hljs-comment">// Replace '...' with the actual value or method of retrieval</span>

<span class="hljs-comment">// Declare and initialize a boolean variable for Input B</span>
<span class="hljs-keyword">boolean</span> B = ...; <span class="hljs-comment">// Replace '...' with the actual value or method of retrieval</span>

<span class="hljs-comment">// Calculate the "AND" operation using only the "NOT" and "OR" operators:</span>
<span class="hljs-comment">// The expression '!A || !B' will be true if either 'A' is false OR 'B' is false.</span>
<span class="hljs-comment">// Thus, by using '!', we are essentially checking if BOTH 'A' and 'B' are true.</span>
<span class="hljs-keyword">boolean</span> ANDResult = !( !A || !B );

<span class="hljs-comment">// Print out the result of the "AND" operation</span>
System.out.println(<span class="hljs-string">"AND Result: "</span> + ANDResult);
</code></pre>
<h3 id="heading-advanced-puzzle"><strong>Advanced Puzzle:</strong></h3>
<p><strong>Problem</strong>: Design a system that takes a sequence of binary inputs and outputs their logical AND, OR, and XOR results.</p>
<p><strong>Solution</strong>: The idea is to loop through the binary sequence and maintain running AND, OR, and XOR results.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Declare an integer array 'binaryInput' containing a sequence of binary values (0s and 1s).</span>
<span class="hljs-comment">// This serves as our sample input.</span>
<span class="hljs-keyword">int</span>[] binaryInput = {<span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>, <span class="hljs-number">0</span>, <span class="hljs-number">1</span>};

<span class="hljs-comment">// Start by initializing the results (AND, OR, XOR) with the first value in the binary sequence.</span>
<span class="hljs-comment">// This will serve as a starting point for our calculations.</span>
<span class="hljs-keyword">int</span> ANDResult = binaryInput[<span class="hljs-number">0</span>]; <span class="hljs-comment">// Start with the first binary value for AND</span>
<span class="hljs-keyword">int</span> ORResult = binaryInput[<span class="hljs-number">0</span>];  <span class="hljs-comment">// Start with the first binary value for OR</span>
<span class="hljs-keyword">int</span> XORResult = binaryInput[<span class="hljs-number">0</span>]; <span class="hljs-comment">// Start with the first binary value for XOR</span>

<span class="hljs-comment">// Use a loop to iterate over the binaryInput array starting from the second element (index 1).</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt; binaryInput.length; i++) {
    <span class="hljs-comment">// For each binary value, update the ANDResult by performing a logical AND operation</span>
    <span class="hljs-comment">// between the current ANDResult and the current binary value.</span>
    ANDResult &amp;= binaryInput[i];

    <span class="hljs-comment">// Similarly, update the ORResult by performing a logical OR operation</span>
    <span class="hljs-comment">// between the current ORResult and the current binary value.</span>
    ORResult |= binaryInput[i];

    <span class="hljs-comment">// For XORResult, perform a logical XOR operation</span>
    <span class="hljs-comment">// between the current XORResult and the current binary value.</span>
    <span class="hljs-comment">// XOR will return 1 only if the two compared bits are different.</span>
    XORResult ^= binaryInput[i];
}

<span class="hljs-comment">// After processing all the binary values, print out the results:</span>
System.out.println(<span class="hljs-string">"Logical AND Result: "</span> + ANDResult); <span class="hljs-comment">// Shows the result of logical AND operation</span>
System.out.println(<span class="hljs-string">"Logical OR Result: "</span> + ORResult);   <span class="hljs-comment">// Shows the result of logical OR operation</span>
System.out.println(<span class="hljs-string">"Logical XOR Result: "</span> + XORResult); <span class="hljs-comment">// Shows the result of logical XOR operation</span>
</code></pre>
<p>Note: This solution assumes a binary sequence using integers 1 and 0. The same logic applies if you were using a boolean array.</p>
<h3 id="heading-control-statements-in-java-if-else-switch">Control Statements in Java – if, else, switch</h3>
<p>Control statements, the core of any programming language's decision-making capabilities, are indispensable when guiding how a program behaves under various scenarios. Consider them your program's "brain," making decisions on its behalf according to certain inputs or conditions. </p>
<p>In Java's vast world of program execution, control statements offer dynamic ways of controlling program flow. In this chapter we will examine three primary ones: if, else and switch.</p>
<h4 id="heading-the-if-statement">The <code>if</code> Statement</h4>
<p>Every decision-making process starts with a question. The <code>if</code> statement in Java serves as this question. It evaluates a given condition: if the condition holds true, it proceeds to execute a specified block of code.</p>
<p><strong>Syntax</strong>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (condition) {
    <span class="hljs-comment">// Block of code to be executed if the condition is true</span>
}
</code></pre>
<p><strong>Example</strong>:</p>
<p>Let's consider voting as an example. The basic criteria to vote in many countries is age. If an individual is 18 or older, they are allowed to vote.</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> age = <span class="hljs-number">20</span>;
<span class="hljs-keyword">if</span> (age &gt;= <span class="hljs-number">18</span>) {
    System.out.println(<span class="hljs-string">"You are eligible to vote."</span>);
}
</code></pre>
<p>In this example, since 20 is greater than 18, the program will output: "You are eligible to vote."</p>
<h4 id="heading-the-if-else-statement">The <code>if-else</code> Statement</h4>
<p>Life is full of choices. Similarly, in programming, there are often two paths to take: one if a condition is met and another if it isn't. The <code>if-else</code> statement in Java caters to this type of situation.</p>
<p><strong>Syntax</strong>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (condition) {
    <span class="hljs-comment">// Block of code executed if condition is true</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Block of code executed if condition is false</span>
}
</code></pre>
<p><strong>Example</strong>:</p>
<p>Continuing with our voting example:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> age = <span class="hljs-number">15</span>;
<span class="hljs-keyword">if</span> (age &gt;= <span class="hljs-number">18</span>) {
    System.out.println(<span class="hljs-string">"You are eligible to vote."</span>);
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"You are not eligible to vote."</span>);
}
</code></pre>
<p>Here, since 15 is less than 18, our program will print: "You are not eligible to vote."</p>
<h4 id="heading-the-if-else-if-ladder">The <code>if-else-if</code> Ladder</h4>
<p>What if there are multiple conditions to check? That's where the <code>if-else-if</code> ladder comes in handy. It allows the program to evaluate a series of conditions in sequence.</p>
<p><strong>Syntax</strong>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (condition1) {
    <span class="hljs-comment">// Executed if condition1 is true</span>
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (condition2) {
    <span class="hljs-comment">// Executed if condition2 is true</span>
} <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Executed if none of the above conditions hold true</span>
}
</code></pre>
<p><strong>Example</strong>:</p>
<p>Suppose we're categorizing grades:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> marks = <span class="hljs-number">75</span>;
<span class="hljs-keyword">if</span> (marks &gt;= <span class="hljs-number">85</span>) {
    System.out.println(<span class="hljs-string">"Grade A"</span>);
} <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (marks &gt;= <span class="hljs-number">70</span>) {
    System.out.println(<span class="hljs-string">"Grade B"</span>);
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"Grade C"</span>);
}
</code></pre>
<p>Given the marks are 75, the program will output: "Grade B".</p>
<h4 id="heading-the-switch-statement">The <code>switch</code> Statement</h4>
<p>When dealing with scenarios where a variable could equate to multiple known values, and each value requires different processing, the <code>switch</code> statement is your tool of choice.</p>
<p><strong>Syntax</strong>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">switch</span> (expression) {
    <span class="hljs-keyword">case</span> value1:
        <span class="hljs-comment">// Code executed for value1</span>
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> value2:
        <span class="hljs-comment">// Code executed for value2</span>
        <span class="hljs-keyword">break</span>;
    <span class="hljs-comment">// You can have any number of case statements</span>
    <span class="hljs-keyword">default</span>:
        <span class="hljs-comment">// Code executed if none of the cases are met</span>
}
</code></pre>
<p><strong>Example</strong>:</p>
<p>For instance, consider a simple day tracker:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> day = <span class="hljs-number">2</span>;
<span class="hljs-keyword">switch</span> (day) {
    <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
        System.out.println(<span class="hljs-string">"Monday"</span>);
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
        System.out.println(<span class="hljs-string">"Tuesday"</span>);
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">default</span>:
        System.out.println(<span class="hljs-string">"Another day"</span>);
}
</code></pre>
<p>Given the day is set to 2, our program will announce that it's "Tuesday".</p>
<p><strong>Cautionary Note</strong>: The <code>break</code> keyword ensures that once a match is found and its corresponding block of code is executed, the program exits the <code>switch</code> block. Omitting it could lead to unintended results as the program "falls through" to subsequent <code>case</code> blocks.</p>
<h4 id="heading-nested-control-statements">Nested Control Statements</h4>
<p>Just like inception, control statements can exist within other control statements. This ability lets developers sculpt intricate logical constructs for detailed decision-making.</p>
<p><strong>Example</strong>:</p>
<p>Consider an eligibility check for driving:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> age = <span class="hljs-number">20</span>;
<span class="hljs-keyword">boolean</span> hasDrivingLicense = <span class="hljs-keyword">true</span>;

<span class="hljs-keyword">if</span> (age &gt;= <span class="hljs-number">18</span>) {
    <span class="hljs-keyword">if</span> (hasDrivingLicense) {
        System.out.println(<span class="hljs-string">"You can drive a car."</span>);
    } <span class="hljs-keyword">else</span> {
        System.out.println(<span class="hljs-string">"You are eligible, but you need a driving license."</span>);
    }
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"You are not eligible to drive."</span>);
}
</code></pre>
<h3 id="heading-practical-scenarios-amp-applications">Practical Scenarios &amp; Applications</h3>
<ul>
<li><strong>User Input Validation</strong>: Using control statements, you can ensure that the input given by the user follows specific criteria. For instance, checking if a user-entered password meets minimum length and contains required characters:</li>
</ul>
<pre><code class="lang-java">String password = userInput(); <span class="hljs-comment">// This is a hypothetical function to get user input</span>
<span class="hljs-keyword">if</span> (password.length() &gt;= <span class="hljs-number">8</span> &amp;&amp; password.contains(<span class="hljs-string">"@"</span>)) {
    System.out.println(<span class="hljs-string">"Password is strong."</span>);
} <span class="hljs-keyword">else</span> {
    System.out.println(<span class="hljs-string">"Password does not meet criteria."</span>);
}
</code></pre>
<ul>
<li><strong>Menu Systems</strong>: Especially in console-based applications, users often choose from a list of options. A <code>switch</code> statement makes implementing this seamless.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> choice = getUserChoice(); <span class="hljs-comment">// Hypothetical function</span>
<span class="hljs-keyword">switch</span>(choice) {
    <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
        showProfile();
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
        editSettings();
        <span class="hljs-keyword">break</span>;
    <span class="hljs-keyword">default</span>:
        System.out.println(<span class="hljs-string">"Invalid choice."</span>);
}
</code></pre>
<ul>
<li><strong>Gaming Logic</strong>: Control statements are important in games. They can determine game outcomes based on player decisions, check winning conditions, or evolve game narratives.</li>
</ul>
<h4 id="heading-exercises-amp-challenges-1">Exercises &amp; Challenges</h4>
<p><strong>Basic Exercise: Basic Calculator</strong></p>
<p>Craft a basic calculator that can execute operations like addition, subtraction, multiplication, and division grounded on user preference using switch statements.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.Scanner;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BasicCalculator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Scanner scanner = <span class="hljs-keyword">new</span> Scanner(System.in);

        <span class="hljs-comment">// Prompt user for input</span>
        System.out.println(<span class="hljs-string">"Enter first number:"</span>);
        <span class="hljs-keyword">double</span> num1 = scanner.nextDouble();

        System.out.println(<span class="hljs-string">"Enter second number:"</span>);
        <span class="hljs-keyword">double</span> num2 = scanner.nextDouble();

        System.out.println(<span class="hljs-string">"Choose operation (+, -, *, /):"</span>);
        <span class="hljs-keyword">char</span> operation = scanner.next().charAt(<span class="hljs-number">0</span>);

        <span class="hljs-comment">// Switch case for calculator operations</span>
        <span class="hljs-keyword">switch</span> (operation) {
            <span class="hljs-keyword">case</span> <span class="hljs-string">'+'</span>:
                System.out.println(<span class="hljs-string">"Result: "</span> + (num1 + num2));
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'-'</span>:
                System.out.println(<span class="hljs-string">"Result: "</span> + (num1 - num2));
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'*'</span>:
                System.out.println(<span class="hljs-string">"Result: "</span> + (num1 * num2));
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">'/'</span>:
                <span class="hljs-keyword">if</span> (num2 != <span class="hljs-number">0</span>) { <span class="hljs-comment">// Avoid division by zero</span>
                    System.out.println(<span class="hljs-string">"Result: "</span> + (num1 / num2));
                } <span class="hljs-keyword">else</span> {
                    System.out.println(<span class="hljs-string">"Cannot divide by zero!"</span>);
                }
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">default</span>:
                System.out.println(<span class="hljs-string">"Invalid operation chosen."</span>);
        }

        scanner.close();
    }
}
</code></pre>
<p><strong>Intermediate Challenge: Traffic Light System</strong></p>
<p>Construct a rudimentary traffic light system. Given a color (Red, Yellow, Green), your program should display corresponding messages, like "Stop" for Red.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.Scanner;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TrafficLightSystem</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Scanner scanner = <span class="hljs-keyword">new</span> Scanner(System.in);

        <span class="hljs-comment">// Prompt user for traffic light color</span>
        System.out.println(<span class="hljs-string">"Enter traffic light color (Red, Yellow, Green):"</span>);
        String color = scanner.nextLine().trim().toLowerCase();

        <span class="hljs-comment">// Switch case for traffic light messages</span>
        <span class="hljs-keyword">switch</span> (color) {
            <span class="hljs-keyword">case</span> <span class="hljs-string">"red"</span>:
                System.out.println(<span class="hljs-string">"Stop"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">"yellow"</span>:
                System.out.println(<span class="hljs-string">"Prepare to stop"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">case</span> <span class="hljs-string">"green"</span>:
                System.out.println(<span class="hljs-string">"Go"</span>);
                <span class="hljs-keyword">break</span>;
            <span class="hljs-keyword">default</span>:
                System.out.println(<span class="hljs-string">"Invalid color entered."</span>);
        }

        scanner.close();
    }
}
</code></pre>
<p><strong>Advanced Puzzle: Student Grade Classification:</strong></p>
<p>Develop a program that classifies student grades (A, B, C, and so forth) relying on given score intervals using the <code>if-else-if</code> ladder.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.Scanner;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">GradeClassification</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Scanner scanner = <span class="hljs-keyword">new</span> Scanner(System.in);

        <span class="hljs-comment">// Prompt user for student score</span>
        System.out.println(<span class="hljs-string">"Enter student score (0-100):"</span>);
        <span class="hljs-keyword">int</span> score = scanner.nextInt();

        <span class="hljs-comment">// Grade classification using if-else-if ladder</span>
        <span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">90</span> &amp;&amp; score &lt;= <span class="hljs-number">100</span>) {
            System.out.println(<span class="hljs-string">"Grade A"</span>);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">80</span> &amp;&amp; score &lt; <span class="hljs-number">90</span>) {
            System.out.println(<span class="hljs-string">"Grade B"</span>);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">70</span> &amp;&amp; score &lt; <span class="hljs-number">80</span>) {
            System.out.println(<span class="hljs-string">"Grade C"</span>);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">60</span> &amp;&amp; score &lt; <span class="hljs-number">70</span>) {
            System.out.println(<span class="hljs-string">"Grade D"</span>);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (score &gt;= <span class="hljs-number">0</span> &amp;&amp; score &lt; <span class="hljs-number">60</span>) {
            System.out.println(<span class="hljs-string">"Grade F"</span>);
        } <span class="hljs-keyword">else</span> {
            System.out.println(<span class="hljs-string">"Invalid score entered."</span>);
        }

        scanner.close();
    }
}
</code></pre>
<h3 id="heading-loops-for-while-do-while-in-java-navigating-repetition">Loops: <code>for</code>, <code>while</code>, <code>do-while</code> in Java – Navigating Repetition</h3>
<p>Loops form the cornerstone of many algorithms and routine tasks in Java. Their primary function is to repeat a block of code multiple times, driven by specific conditions. </p>
<p>This section offers a deep dive into the core loop constructs available in Java: the <code>for</code>, <code>while</code>, and <code>do-while</code> loops.</p>
<h4 id="heading-the-for-loop">The <code>for</code> Loop</h4>
<p>The <code>for</code> loop provides a concise way to iterate over a range of values or elements in a collection. It's typically used when the number of iterations is known beforehand.</p>
<p><strong>Syntax</strong>:</p>
<pre><code class="lang-java"><span class="hljs-keyword">for</span> (initialization; condition; increment/decrement) {
    <span class="hljs-comment">// Block of code to be repeated</span>
}
</code></pre>
<p><strong>Example</strong>:</p>
<p>To print numbers from 1 to 5:</p>
<pre><code class="lang-java"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">5</span>; i++) {
    System.out.println(i);
}
</code></pre>
<p><strong>Points to Remember:</strong></p>
<ul>
<li>Initialization: Sets a starting point for the loop.</li>
<li>Condition: If this evaluates to <code>true</code>, the loop continues – otherwise, it stops.</li>
<li>Increment/Decrement: Modifies the loop variable after each iteration.</li>
</ul>
<h4 id="heading-the-while-loop">The <code>while</code> Loop</h4>
<p>The <strong><code>while</code></strong> loop repeatedly executes a block of code as long as a specified condition evaluates to <strong><code>true</code></strong>.</p>
<p><strong>Syntax:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">while</span> (condition) {
    <span class="hljs-comment">// Block of code to be repeated</span>
}
</code></pre>
<p><strong>Example:</strong></p>
<p>To print numbers from 1 to 5:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>;
<span class="hljs-keyword">while</span> (i &lt;= <span class="hljs-number">5</span>) {
    System.out.println(i);
    i++;
}
</code></pre>
<p><strong>Points to Remember:</strong></p>
<p>Ensure the condition in a while loop eventually becomes false. Otherwise, you'll have an infinite loop.</p>
<h4 id="heading-the-do-while-loop">The <code>do-while</code> Loop</h4>
<p>Similar to the <code>while</code> loop, but with a critical difference: the <code>do-while</code> loop checks its condition <strong>after</strong> the loop has executed, guaranteeing the loop's body will run at least once.</p>
<p><strong>Syntax:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">do</span> {
    <span class="hljs-comment">// Block of code to be repeated</span>
} <span class="hljs-keyword">while</span> (condition);
</code></pre>
<p><strong>Example:</strong></p>
<p>Prompting user input until a valid number is received:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> number;
<span class="hljs-keyword">do</span> {
    System.out.println(<span class="hljs-string">"Enter a number between 1 and 10:"</span>);
    number = scanner.nextInt();
} <span class="hljs-keyword">while</span> (number &lt; <span class="hljs-number">1</span> || number &gt; <span class="hljs-number">10</span>);
</code></pre>
<p><strong>Points to Remember:</strong></p>
<p>Use the <code>do-while</code> loop when the loop's body must execute at least once, regardless of the condition's initial state.</p>
<h4 id="heading-enhanced-for-loop-for-each">Enhanced <code>for-loop</code> (<code>for-each</code>)</h4>
<p>Introduced in Java 5, the enhanced for loop simplifies iterating over collections and arrays.</p>
<p><strong>Syntax:</strong></p>
<pre><code class="lang-java"><span class="hljs-keyword">for</span> (Type variable : collection/array) {
    <span class="hljs-comment">// Block of code</span>
}
</code></pre>
<p><strong>Example</strong>:</p>
<p>Printing all elements in an array:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span>[] numbers = {<span class="hljs-number">1</span>, <span class="hljs-number">2</span>, <span class="hljs-number">3</span>, <span class="hljs-number">4</span>, <span class="hljs-number">5</span>};
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : numbers) {
    System.out.println(num);
}
</code></pre>
<p><strong>Points to Remember:</strong></p>
<p>The enhanced for loop is read-only. This means that you cannot modify the current element during iteration.</p>
<h4 id="heading-loop-control-statements">Loop Control Statements</h4>
<ul>
<li><code>break</code>: Exits the current loop immediately.</li>
<li><code>continue</code>: Skips the rest of the current iteration and proceeds to the next iteration.</li>
</ul>
<p><strong>Example:</strong></p>
<p>Print numbers from 1 to 10 but skip 5:</p>
<pre><code class="lang-java"><span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">10</span>; i++) {
    <span class="hljs-keyword">if</span> (i == <span class="hljs-number">5</span>) {
        <span class="hljs-keyword">continue</span>;
    }
    System.out.println(i);
}
</code></pre>
<h4 id="heading-practical-scenarios-amp-applications-1">Practical Scenarios &amp; Applications:</h4>
<p><strong>Iterating Over Large Data Sets</strong>: In data-driven applications, large datasets (like those in databases, files, or even arrays/lists) often need to be processed. Loops make it feasible to traverse each data element sequentially, applying operations like transformation, computation, or simply extraction.</p>
<p><strong>Example</strong>: Imagine you have a list of 10,000 employees, and you want to calculate the average salary:</p>
<pre><code class="lang-java"><span class="hljs-keyword">double</span> totalSalary = <span class="hljs-number">0</span>;
<span class="hljs-keyword">int</span> numberOfEmployees = employeesList.size();

<span class="hljs-keyword">for</span> (Employee emp : employeesList) {
    totalSalary += emp.getSalary();
}

<span class="hljs-keyword">double</span> averageSalary = totalSalary / numberOfEmployees;
System.out.println(<span class="hljs-string">"Average Salary: "</span> + averageSalary);
</code></pre>
<p><strong>Game Loops Where the Game State is Repeatedly Updated</strong>: Most video games operate on a continuous loop, known as the "game loop." Within this loop, user inputs are processed, game state and physics are updated, and visuals are rendered. This loop runs numerous times per second.</p>
<p><strong>Example</strong>: A basic game loop might look like this:</p>
<pre><code class="lang-java"><span class="hljs-keyword">while</span> (gameIsRunning) {
    processUserInputs();  <span class="hljs-comment">// e.g., move character, jump, etc.</span>
    updateGameState();    <span class="hljs-comment">// e.g., move non-player characters, update scores, etc.</span>
    renderGraphics();     <span class="hljs-comment">// draw the current state of the game on the screen</span>
    delay(<span class="hljs-number">16</span>);            <span class="hljs-comment">// a simple way to aim for ~60 frames per second</span>
}
</code></pre>
<p><strong>User Input Validation</strong>: When taking inputs from users, there's no guarantee they'll provide valid data. Loops can be used to repeatedly prompt users until valid input is received.</p>
<p><strong>Example</strong>: A program asking the user for a number between 1 and 100 might use a loop like this:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span> userInput;
<span class="hljs-keyword">do</span> {
    System.out.println(<span class="hljs-string">"Enter a number between 1 and 100:"</span>);
    userInput = scanner.nextInt();
} <span class="hljs-keyword">while</span> (userInput &lt; <span class="hljs-number">1</span> || userInput &gt; <span class="hljs-number">100</span>);
</code></pre>
<p><strong>Searching and Sorting Algorithms</strong>: Searching and sorting are fundamental operations in computer science, and both heavily depend on loops. Whether it's a simple linear search or a complex merge sort, loops are integral.</p>
<p><strong>Examples</strong>:</p>
<p><strong>Linear Search</strong>: To search for a value in an array:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span>[] numbers = {<span class="hljs-number">10</span>, <span class="hljs-number">20</span>, <span class="hljs-number">30</span>, <span class="hljs-number">40</span>, <span class="hljs-number">50</span>};
<span class="hljs-keyword">int</span> valueToFind = <span class="hljs-number">30</span>;
<span class="hljs-keyword">boolean</span> found = <span class="hljs-keyword">false</span>;

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> num : numbers) {
    <span class="hljs-keyword">if</span> (num == valueToFind) {
        found = <span class="hljs-keyword">true</span>;
        <span class="hljs-keyword">break</span>;
    }
}

<span class="hljs-keyword">if</span> (found) {
    System.out.println(valueToFind + <span class="hljs-string">" was found in the array."</span>);
} <span class="hljs-keyword">else</span> {
    System.out.println(valueToFind + <span class="hljs-string">" was not found in the array."</span>);
}
</code></pre>
<p><strong>Bubble Sort</strong>: A simple sorting algorithm that repeatedly steps through the list, compares adjacent elements, and swaps them if they are in the wrong order:</p>
<pre><code class="lang-java"><span class="hljs-keyword">int</span>[] numbers = {<span class="hljs-number">64</span>, <span class="hljs-number">34</span>, <span class="hljs-number">25</span>, <span class="hljs-number">12</span>, <span class="hljs-number">22</span>, <span class="hljs-number">11</span>, <span class="hljs-number">90</span>};
<span class="hljs-keyword">int</span> n = numbers.length;

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">0</span>; i &lt; n-<span class="hljs-number">1</span>; i++) {
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> j = <span class="hljs-number">0</span>; j &lt; n-i-<span class="hljs-number">1</span>; j++) {
        <span class="hljs-keyword">if</span> (numbers[j] &gt; numbers[j+<span class="hljs-number">1</span>]) {
            <span class="hljs-comment">// swap numbers[j] and numbers[j+1]</span>
            <span class="hljs-keyword">int</span> temp = numbers[j];
            numbers[j] = numbers[j+<span class="hljs-number">1</span>];
            numbers[j+<span class="hljs-number">1</span>] = temp;
        }
    }
}
</code></pre>
<p>By understanding these practical applications of loops, you'll gain a clearer insight into their utility and indispensability in various programming scenarios.</p>
<h4 id="heading-exercises-amp-challenges-2">Exercises &amp; Challenges:</h4>
<p>Programming is a journey of solving real-world problems by translating them into a language that computers can understand. </p>
<p>While theory provides us with the tools, it's through hands-on problem-solving that we truly internalize the essence of programming. The exercises that follow are designed to take you through such hands-on experiences.</p>
<p><strong>Basic Exercise: Fibonacci Numbers Using a While Loop</strong></p>
<p>The Fibonacci sequence is a series of numbers where a number is the sum of the two preceding ones, starting from 0 and 1. This sequence has a rich historical context and can be found in many parts of nature, from the spirals of galaxies to shells to the pattern of leaves. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/11/shell.jpg" alt="Image" width="600" height="400" loading="lazy">
<em>Image showing a shell displaying how the Fibonacci sequence can be found in nature</em></p>
<p>The challenge here is to use the <code>while</code> loop, a control structure that keeps executing its block until a specified condition is met, to generate this intriguing sequence.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FibonacciWhileLoop</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">int</span> n = <span class="hljs-number">10</span>;  <span class="hljs-comment">// Number of Fibonacci numbers to print</span>
        <span class="hljs-keyword">int</span> t1 = <span class="hljs-number">0</span>, t2 = <span class="hljs-number">1</span>;

        <span class="hljs-keyword">int</span> count = <span class="hljs-number">1</span>;  <span class="hljs-comment">// To keep track of how many numbers have been printed</span>

        <span class="hljs-comment">// Print the first two Fibonacci numbers</span>
        System.out.print(<span class="hljs-string">"First "</span> + n + <span class="hljs-string">" Fibonacci numbers: "</span> + t1 + <span class="hljs-string">", "</span> + t2);

        <span class="hljs-comment">// Use a while loop to calculate the rest of the numbers</span>
        <span class="hljs-keyword">while</span> (count &lt;= n - <span class="hljs-number">2</span>) {
            <span class="hljs-keyword">int</span> sum = t1 + t2;
            System.out.print(<span class="hljs-string">", "</span> + sum);
            t1 = t2;
            t2 = sum;
            count++;
        }
    }
}
</code></pre>
<p><strong>Intermediate Challenge: Menu-Driven Program</strong></p>
<p>A common application in software development is the creation of menu-driven programs. These are interactive programs that allow users to choose from a list of options, leading them through different functionalities of an application. </p>
<p>Using the <code>do-while</code> loop, we aim to design a basic structure for such a program. The loop ensures that the menu is presented to the user until they decide to exit, allowing for repeated interactions.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.Scanner;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MenuDrivenProgram</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Scanner scanner = <span class="hljs-keyword">new</span> Scanner(System.in);

        <span class="hljs-comment">// Start with a do-while loop to keep showing the menu until the user chooses to exit</span>
        <span class="hljs-keyword">int</span> choice;
        <span class="hljs-keyword">do</span> {
            <span class="hljs-comment">// Print out the menu</span>
            System.out.println(<span class="hljs-string">"\\nMenu:"</span>);
            System.out.println(<span class="hljs-string">"1. Calculator"</span>);
            System.out.println(<span class="hljs-string">"2. Conversion Tools"</span>);
            System.out.println(<span class="hljs-string">"3. Exit"</span>);
            System.out.print(<span class="hljs-string">"Enter your choice: "</span>);

            choice = scanner.nextInt();

            <span class="hljs-keyword">switch</span> (choice) {
                <span class="hljs-keyword">case</span> <span class="hljs-number">1</span>:
                    System.out.println(<span class="hljs-string">"Calculator chosen!"</span>);
                    <span class="hljs-comment">// Implement the calculator here...</span>
                    <span class="hljs-keyword">break</span>;
                <span class="hljs-keyword">case</span> <span class="hljs-number">2</span>:
                    System.out.println(<span class="hljs-string">"Conversion tools chosen!"</span>);
                    <span class="hljs-comment">// Implement conversion tools here...</span>
                    <span class="hljs-keyword">break</span>;
                <span class="hljs-keyword">case</span> <span class="hljs-number">3</span>:
                    System.out.println(<span class="hljs-string">"Exiting the program. Goodbye!"</span>);
                    <span class="hljs-keyword">break</span>;
                <span class="hljs-keyword">default</span>:
                    System.out.println(<span class="hljs-string">"Invalid choice! Please select from the menu."</span>);
                    <span class="hljs-keyword">break</span>;
            }
        } <span class="hljs-keyword">while</span> (choice != <span class="hljs-number">3</span>);  <span class="hljs-comment">// Exit when user chooses 3</span>

        scanner.close();
    }
}
</code></pre>
<p><strong>Advanced Puzzle: FizzBuzz Using a For Loop</strong></p>
<p>FizzBuzz is a classic programming puzzle, often used in interviews to gauge a candidate's understanding of logic and control structures. The problem might seem simple but is quite effective at illustrating the concept of condition-based execution. </p>
<p>Using the <code>for</code> loop, a control structure that iterates over a sequence, we'll implement this popular challenge.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FizzBuzz</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">for</span> (<span class="hljs-keyword">int</span> i = <span class="hljs-number">1</span>; i &lt;= <span class="hljs-number">100</span>; i++) { <span class="hljs-comment">// Looping through numbers 1 to 100</span>
            <span class="hljs-comment">// If number is divisible by 3 and 5, print "FizzBuzz"</span>
            <span class="hljs-keyword">if</span> (i % <span class="hljs-number">3</span> == <span class="hljs-number">0</span> &amp;&amp; i % <span class="hljs-number">5</span> == <span class="hljs-number">0</span>) {
                System.out.println(<span class="hljs-string">"FizzBuzz"</span>);
            }
            <span class="hljs-comment">// If number is divisible by 3, print "Fizz"</span>
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (i % <span class="hljs-number">3</span> == <span class="hljs-number">0</span>) {
                System.out.println(<span class="hljs-string">"Fizz"</span>);
            }
            <span class="hljs-comment">// If number is divisible by 5, print "Buzz"</span>
            <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (i % <span class="hljs-number">5</span> == <span class="hljs-number">0</span>) {
                System.out.println(<span class="hljs-string">"Buzz"</span>);
            }
            <span class="hljs-comment">// If number is not divisible by either 3 or 5, print the number</span>
            <span class="hljs-keyword">else</span> {
                System.out.println(i);
            }
        }
    }
}
</code></pre>
<h2 id="heading-chapter-4-object-oriented-programming-oop">Chapter 4: Object-Oriented Programming (OOP)</h2>
<p>At this juncture in our journey through Java programming, it's time to go deeper into the concepts of Object-Oriented Programming (OOP). Equipped with the fundamental skills you've learned during the preceeding chapters, you now stand at a crucial juncture: OOP is at Java's heart. </p>
<p>By diving headfirst into its complex layers, you are prepared to unlock its secrets while drawing parallels back to earlier fundamental concepts you've already mastered.</p>
<p>In my own journey with Java, I recall the powerful mix of enthusiasm and uncertainty that defined its beginning stages for me. </p>
<p>Like Bill Cage in "Edge of Tomorrow," my introduction was sudden yet disorienting. I was thrust into advanced topics such as inheritance and encapsulation without understanding foundational elements like methods or loops. This felt like being thrust onto an unfamiliar aircraft without prior instruction or guidance.</p>
<p>Adversity in learning often results in greater comprehension. And you're now ready, equipped with the essential programming knowledge to navigate OOP without experiencing its initial disorientation like I had. </p>
<p>OOP in Java goes beyond being just another chapter – it represents Java's essence. Here we fully leverage its abilities, simulating real world complexities accurately while building upon prior lessons accumulated over time. This next phase will bring you insightful as well as instinctive learning experiences.</p>
<h3 id="heading-what-is-object-oriented-programming">What is Object-Oriented Programming?</h3>
<p>OOP (Object Oriented Programming) centers around classes and objects as the cornerstones. A class serves as the blueprint, much like architectural plans are used when constructing multiple buildings. Similarly multiple objects may be instantiated from one class. </p>
<p>Imagine it this way: think of a prototype class displaying attributes and behaviors while its manifestation exists as a tangible manifestation.</p>
<h3 id="heading-understanding-classes-in-java-the-blueprint">Understanding Classes in Java: The Blueprint</h3>
<p>At its essence, a class encapsulates data for the object and methods to manipulate that data. The data, or attributes, represents the state, and the methods define behavior.</p>
<h4 id="heading-how-to-declare-and-define-a-class-in-java">How to Declare and Define a Class in Java</h4>
<p>A class in Java is introduced using the <code>class</code> keyword, followed by its name.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
    String color;  <span class="hljs-comment">// attribute</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">drive</span><span class="hljs-params">()</span> </span>{  <span class="hljs-comment">// method</span>
        System.out.println(<span class="hljs-string">"Car is driving"</span>);
    }
}
</code></pre>
<h4 id="heading-objects-in-java-instances-of-classes">Objects in Java: Instances of Classes</h4>
<p>An object is a specific instance of a class. Each object has a unique identity but shares the structure provided by its class.</p>
<p>Objects are instantiated using the <code>new</code> keyword.</p>
<pre><code class="lang-java">Car myCar = <span class="hljs-keyword">new</span> Car();
</code></pre>
<p>Post-instantiation, the object's attributes and methods can be accessed using the dot operator.</p>
<pre><code class="lang-java">myCar.color = <span class="hljs-string">"Red"</span>;
myCar.drive();
</code></pre>
<h4 id="heading-constructors-the-object-initializers">Constructors: The Object Initializers</h4>
<p>Constructors play a pivotal role in object instantiation, allowing for immediate attribute setting.</p>
<ul>
<li><strong>Default Constructor</strong>: Provided by Java if no constructor is defined.</li>
<li><strong>Parameterized Constructor</strong>: Accepts parameters to initialize attributes.</li>
<li><strong>Constructor Overloading</strong>: Multiple constructors with different parameters.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
    String color;
    Car() {
        <span class="hljs-keyword">this</span>.color = <span class="hljs-string">"Unknown"</span>;
    }
    Car(String c) {
        <span class="hljs-keyword">this</span>.color = c;
    }
}
</code></pre>
<h4 id="heading-the-this-keyword-in-java">The <code>this</code> Keyword in Java</h4>
<p>The <code>this</code> keyword refers to the current instance of an object. It's particularly useful when differentiating instance variables from method parameters.</p>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setColor</span><span class="hljs-params">(String color)</span> </span>{
    <span class="hljs-keyword">this</span>.color = color;
}
</code></pre>
<h4 id="heading-garbage-collection-and-destructors">Garbage Collection and Destructors</h4>
<p>Java inherently handles memory management. Objects no longer in use are automatically cleared by the garbage collector. The <code>finalize()</code> method allows an object to clean up resources before it's removed.</p>
<h4 id="heading-static-vs-non-static">Static vs. Non-static</h4>
<p>A <strong><code>static</code></strong> member belongs to the class itself, rather than any specific instance. For instance, a static variable will share its value across all instances of the class. Non-static members, conversely, are unique to each instance.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> carCount;  <span class="hljs-comment">// static variable</span>
    Car() {
        carCount++;
    }
</code></pre>
<h4 id="heading-the-final-keyword-with-classes-and-objects">The <code>Final</code> Keyword with Classes and Objects</h4>
<p>The <code>final</code> keyword, when applied, ensures immutability. A final variable can't be modified, a final method can't be overridden, and a final class can't be subclassed.</p>
<pre><code class="lang-java"><span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImmutableCar</span> </span>{}
</code></pre>
<h4 id="heading-real-world-analogies-amp-practical-applications">Real-world Analogies &amp; Practical Applications</h4>
<p>In the world of programming, understanding complex concepts through simple, relatable analogies can be a game-changer. </p>
<p>This solution dives into the analogy of a cookie cutter representing a Java class and cookies as its objects. Let's implement this to understand how a class provides structure, while objects of the class can have variations.</p>
<p><strong>Java Implementation:</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// The CookieCutter class represents the analogy's cookie cutter.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CookieCutter</span> </span>{

    <span class="hljs-comment">// Common shape for all cookies made using this cutter.</span>
    String shape;

    <span class="hljs-comment">// Constructor to initialize the shape of the cookie cutter.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">CookieCutter</span><span class="hljs-params">(String shape)</span> </span>{
        <span class="hljs-keyword">this</span>.shape = shape;
    }

    <span class="hljs-comment">// Method to create a new cookie with the specified flavor using this cutter's shape.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> Cookie <span class="hljs-title">makeCookie</span><span class="hljs-params">(String flavor)</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Cookie(<span class="hljs-keyword">this</span>.shape, flavor);
    }
}

<span class="hljs-comment">// The Cookie class represents the cookies made using the cookie cutter.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cookie</span> </span>{

    <span class="hljs-comment">// Every cookie will have a shape and a flavor.</span>
    String shape;
    String flavor;

    <span class="hljs-comment">// Constructor to initialize the shape and flavor of the cookie.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Cookie</span><span class="hljs-params">(String shape, String flavor)</span> </span>{
        <span class="hljs-keyword">this</span>.shape = shape;
        <span class="hljs-keyword">this</span>.flavor = flavor;
    }

    <span class="hljs-comment">// Method to describe the cookie.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">describe</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"This is a "</span> + flavor + <span class="hljs-string">" flavored "</span> + shape + <span class="hljs-string">" cookie."</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CookieFactory</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{

        <span class="hljs-comment">// Creating a heart-shaped cookie cutter.</span>
        CookieCutter heartShapedCutter = <span class="hljs-keyword">new</span> CookieCutter(<span class="hljs-string">"heart"</span>);

        <span class="hljs-comment">// Using the heart-shaped cutter to create cookies with different flavors.</span>
        Cookie chocoHeartCookie = heartShapedCutter.makeCookie(<span class="hljs-string">"chocolate"</span>);
        Cookie vanillaHeartCookie = heartShapedCutter.makeCookie(<span class="hljs-string">"vanilla"</span>);

        <span class="hljs-comment">// Describing the cookies.</span>
        chocoHeartCookie.describe();
        vanillaHeartCookie.describe();
    }
}
</code></pre>
<p><strong>Expected Output:</strong></p>
<pre><code class="lang-java">This is a chocolate flavored heart cookie.
This is a vanilla flavored heart cookie.
</code></pre>
<p><strong>Explanation:</strong></p>
<ol>
<li>We've defined a <code>CookieCutter</code> class, representing the cookie cutter. It has an attribute <code>shape</code> and a method <code>makeCookie</code> to create cookies of a particular flavor but with the cutter's shape.</li>
<li>The <code>Cookie</code> class represents individual cookies. Each cookie has a <code>shape</code> and <code>flavor</code>.</li>
<li>In the <code>CookieFactory</code> main class, we created a heart-shaped <code>CookieCutter</code> and used it to make two different flavored cookies. Despite the flavor difference, both cookies retain the heart shape.</li>
</ol>
<p>In conclusion, much like our analogy, the <code>CookieCutter</code> class dictates the structure (shape) while allowing individual objects (<code>Cookie</code>) to possess unique attributes (flavor).</p>
<h4 id="heading-exercises-and-practice-questions">Exercises and Practice Questions</h4>
<ol>
<li>Design a <code>Person</code> class with attributes like <code>name</code> and <code>age</code>, and methods such as <code>speak()</code>.</li>
<li>Instantiate three different <code>Person</code> objects and call their methods.</li>
<li>Experiment with creating constructors, using the <code>this</code> keyword, and making static variables.</li>
</ol>
<p>Understanding the basic structure of a class and the instantiation of objects is fundamental to Java programming. In this exercise, we'll design a simple <code>Person</code> class, explore object instantiation, and dive into constructors, the <code>this</code> keyword, and static variables.</p>
<p><strong>Java Implementation:</strong></p>
<pre><code class="lang-java">javaCopy code
<span class="hljs-comment">// Definition of the Person class.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{

    <span class="hljs-comment">// Attributes of the Person class.</span>
    String name;
    <span class="hljs-keyword">int</span> age;

    <span class="hljs-comment">// Static variable to keep count of the number of Person objects created.</span>
    <span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> personCount = <span class="hljs-number">0</span>;

    <span class="hljs-comment">// Default constructor.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">()</span> </span>{
        personCount++; <span class="hljs-comment">// Increment the count whenever a new Person object is created.</span>
    }

    <span class="hljs-comment">// Parameterized constructor using the 'this' keyword to initialize the attributes.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name, <span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.age = age;
        personCount++; <span class="hljs-comment">// Increment the count whenever a new Person object is created.</span>
    }

    <span class="hljs-comment">// speak() method to let the person introduce themselves.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">speak</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Hello! My name is "</span> + name + <span class="hljs-string">" and I am "</span> + age + <span class="hljs-string">" years old."</span>);
    }

    <span class="hljs-comment">// Static method to display the number of Person objects created.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">displayCount</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Total number of persons: "</span> + personCount);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PersonTest</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{

        <span class="hljs-comment">// Instantiating three different Person objects.</span>
        Person person1 = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Alice"</span>, <span class="hljs-number">25</span>);
        Person person2 = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Bob"</span>, <span class="hljs-number">30</span>);
        Person person3 = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"Charlie"</span>, <span class="hljs-number">35</span>);

        <span class="hljs-comment">// Calling the speak() method for each Person object.</span>
        person1.speak();
        person2.speak();
        person3.speak();

        <span class="hljs-comment">// Displaying the number of Person objects created using the static method.</span>
        Person.displayCount();
    }
}
</code></pre>
<p><strong>Expected Output:</strong></p>
<pre><code class="lang-mathematica">Hello! My name is Alice and I am 25 years old.
Hello! My name is Bob and I am 30 years old.
Hello! My name is Charlie and I am 35 years old.
Total number of persons: 3
</code></pre>
<p><strong>Explanation:</strong></p>
<ol>
<li>We've created the <code>Person</code> class with attributes <code>name</code> and <code>age</code>.</li>
<li>We've also included a static variable <code>personCount</code> to keep track of the number of <code>Person</code> objects instantiated.</li>
<li>Two constructors are provided: a default constructor and a parameterized constructor. The <code>this</code> keyword in the parameterized constructor helps distinguish between instance variables and constructor parameters.</li>
<li>The <code>speak()</code> method lets a person introduce themselves.</li>
<li>The static method <code>displayCount()</code> showcases the use of the static variable and provides a count of the number of <code>Person</code> objects created.</li>
<li>In the <code>PersonTest</code> main class, we've instantiated three <code>Person</code> objects and invoked their methods.</li>
</ol>
<p>Through this implementation, we've successfully encapsulated the foundational concepts of class design, object instantiation, constructors, the <code>this</code> keyword, and static variables in Java.</p>
<h3 id="heading-understanding-constructors">Understanding Constructors</h3>
<p>A constructor in Java is a special block of code that initializes the newly created object. It holds the same name as its class and behaves like a method, though it doesn’t have any return type. Constructors breathe life into an object, setting initial values and ensuring that the object is in a valid state upon creation.</p>
<h4 id="heading-types-of-constructors">Types of Constructors:</h4>
<p><strong>Default Constructor:</strong> A default constructor is one without parameters. If not explicitly defined, Java provides one implicitly to ensure every class has a constructor.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
    <span class="hljs-comment">// Default constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-comment">// Initialization process</span>
    }
}
</code></pre>
<p><strong>Parameterized Constructor:</strong> At times, it's beneficial to initialize an object with specific values. This is where parameterized constructors come into play.</p>
<p>Unlike the default constructor, parameterized constructors accept arguments to initialize the attributes of the object.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
    <span class="hljs-keyword">int</span> a;
    <span class="hljs-comment">// Parameterized constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x)</span> </span>{
        a = x;
    }
}
</code></pre>
<p><strong>Constructor Overloading:</strong> Constructors can be overloaded, much like methods. This means a class can have multiple constructors, differentiated by their parameter list.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
    <span class="hljs-keyword">int</span> a, b;
    <span class="hljs-comment">// Constructor with one parameter</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x)</span> </span>{
        a = x;
    }
    <span class="hljs-comment">// Constructor with two parameters</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x, <span class="hljs-keyword">int</span> y)</span> </span>{
        a = x;
        b = y;
    }
}
</code></pre>
<p>This flexibility ensures objects can be initialized in multiple ways as per the requirement.</p>
<p><strong><code>this</code> Keyword in Constructors:</strong> Often, parameter names in a constructor might conflict with instance variable names. The <code>this</code> keyword helps differentiate.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
    <span class="hljs-keyword">int</span> a;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a)</span> </span>{
        <span class="hljs-keyword">this</span>.a = a; <span class="hljs-comment">// Differentiating using 'this'</span>
    }
}
</code></pre>
<p><strong>The <code>super()</code> Call:</strong> The <strong><code>super()</code></strong> call proves invaluable. It invokes the parent class constructor, ensuring a structured initialization.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parent</span> </span>{
    <span class="hljs-comment">// Parent class constructor</span>
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Parent</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Child</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">super</span>(); <span class="hljs-comment">// Calling parent constructor</span>
    }
}
</code></pre>
<p><strong>Copy Constructor:</strong> A copy constructor, as the name suggests, copies the values of one object into another.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
    <span class="hljs-keyword">int</span> a;
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">(MyClass obj)</span> </span>{
        a = obj.a; <span class="hljs-comment">// Copying value</span>
    }
}
</code></pre>
<p><strong>Chaining Constructors:</strong> A constructor can call another constructor in the same class using this.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MyClass</span> </span>{
    <span class="hljs-keyword">int</span> a, b;
    <span class="hljs-comment">// Default constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">this</span>(<span class="hljs-number">0</span>); <span class="hljs-comment">// Calling parameterized constructor</span>
    }
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">MyClass</span><span class="hljs-params">(<span class="hljs-keyword">int</span> x)</span> </span>{
        a = x;
    }
}
</code></pre>
<h4 id="heading-practical-examples-amp-use-cases">Practical Examples &amp; Use Cases:</h4>
<p>Throughout the Java ecosystem, constructors lay the groundwork, whether it's in creating simple objects or intricate structures like GUI components. Examining code snippets from popular Java libraries can offer insightful applications of constructors.</p>
<p>Now let's talk about some best practices when working with constructors:</p>
<p>Constructors should remain clutter-free, focusing solely on initialization. Avoid heavy computations and, importantly, be cautious of calling overridable methods in constructors.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Base</span> </span>{
    <span class="hljs-comment">// Overridable method</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Base setup"</span>);
    }

    <span class="hljs-comment">// Base constructor</span>
    Base() {
        System.out.println(<span class="hljs-string">"Base constructor"</span>);
        <span class="hljs-comment">// Calling overridable method inside constructor</span>
        setup();
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Derived</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Base</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> value;

    <span class="hljs-comment">// Overriding the setup method</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setup</span><span class="hljs-params">()</span> </span>{
        value = <span class="hljs-number">42</span>;
        System.out.println(<span class="hljs-string">"Derived setup with value: "</span> + value);
    }

    <span class="hljs-comment">// Derived class constructor</span>
    Derived() {
        System.out.println(<span class="hljs-string">"Derived constructor"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Derived d = <span class="hljs-keyword">new</span> Derived();
        System.out.println(<span class="hljs-string">"Derived object value: "</span> + d.value);
    }
}
</code></pre>
<p>When you run the above code, the output will be:</p>
<pre><code class="lang-kotlin">kotlinCopy code
Base <span class="hljs-keyword">constructor</span>
Derived setup with value: <span class="hljs-number">42</span>
Derived <span class="hljs-keyword">constructor</span>
Derived <span class="hljs-keyword">object</span> value: <span class="hljs-number">0</span>
</code></pre>
<p>What's going on in this code?</p>
<ul>
<li>When the <code>Derived</code> class object is created, the base class constructor is called first.</li>
<li>Within the base class constructor, the <code>setup</code> method is invoked. Since this method is overridden in the derived class, the derived class's version of <code>setup</code> is executed. Here, <code>value</code> is set to 42.</li>
<li>After the base constructor completes, the derived class constructor runs.</li>
<li>However, after everything, the value of <code>value</code> in the derived object remains 0 because instance variable initializations occur after the superclass constructor has completed but before the derived class constructor body is executed. This causes a misleading situation.</li>
</ul>
<p>The call to the overridable method (<code>setup</code>) within the base class constructor leads to unpredictable behavior. Avoid calling overridable methods inside constructors. Always aim for constructors to be simple, straightforward, and focused solely on initialization.</p>
<h4 id="heading-exercises-and-practice-questions-1">Exercises and Practice Questions:</h4>
<p>The following challenges range from creating simple classes to deciphering constructor-related code snippets.</p>
<p><strong>Challenge 1: Basic – Create a Simple Class</strong></p>
<ol>
<li>Design a class named <code>Book</code> with two attributes: <code>title</code> and <code>author</code>.</li>
<li>Implement a method <code>showBookInfo</code> which prints the book's title and author.</li>
<li>Instantiate the class and call the method to display a book's details.</li>
</ol>
<p><strong>Challenge 2: Intermediate – Working with Default Constructors</strong></p>
<ol>
<li>Using the <code>Book</code> class from Challenge 1, create a default constructor that initializes the <code>title</code> and <code>author</code> to "Unknown".</li>
<li>Instantiate the class without passing any arguments and use the <code>showBookInfo</code> method. Verify that it displays "Unknown" for both title and author.</li>
</ol>
<p><strong>Challenge 3: Intermediate – Introducing Parameterized Constructors</strong></p>
<ol>
<li>Enhance the <code>Book</code> class to have a parameterized constructor that accepts the title and author of the book.</li>
<li>Instantiate the class by passing specific book details and then use the <code>showBookInfo</code> method. Ensure it displays the passed details correctly.</li>
</ol>
<p><strong>Challenge 4: Advanced – Constructor Overloading</strong></p>
<ol>
<li>In the <code>Book</code> class, add another parameterized constructor that only accepts a title (the author is set to "Unknown").</li>
<li>Create objects using both constructors to ensure overloading works as expected.</li>
</ol>
<p><strong>Challenge 5: Expert – <code>this</code> Keyword in Action</strong></p>
<ol>
<li>Modify the <code>Book</code> class so that the parameter names in the constructors are the same as the class attributes.</li>
<li>Utilize the <code>this</code> keyword to differentiate between instance variables and constructor parameters.</li>
<li>Instantiate the class and verify that attributes are still correctly initialized.</li>
</ol>
<p><strong>Challenge 6: Super Expert – Analyze Constructor Flow</strong> Given the following code snippet:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parent</span> </span>{
    Parent() {
        System.out.println(<span class="hljs-string">"Parent Constructor"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Parent</span> </span>{
    Child() {
        System.out.println(<span class="hljs-string">"Child Constructor"</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConstructorFlow</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Child obj = <span class="hljs-keyword">new</span> Child();
    }
}
</code></pre>
<ol>
<li>Predict the output without running the code.</li>
<li>Execute the code to confirm your prediction.</li>
<li>Modify the <code>Parent</code> and <code>Child</code> classes to include parameterized constructors. Ensure the child class calls the parent's parameterized constructor using the <code>super</code> keyword. Verify the flow by instantiating the <code>Child</code> class with necessary parameters.</li>
</ol>
<p>Engaging with these challenges will offer a progression in understanding constructors, from their basic usage to more nuanced aspects. As always, practice is key to a deeper understanding.</p>
<p><strong>Solution to Challenge 1: Basic – Create a Simple Class</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> </span>{
    <span class="hljs-comment">// Attributes for the Book class</span>
    String title;
    String author;

    <span class="hljs-comment">// Method to display book information</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showBookInfo</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Title: "</span> + title + <span class="hljs-string">", Author: "</span> + author);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Creating an object of the Book class</span>
        Book myBook = <span class="hljs-keyword">new</span> Book();
        myBook.title = <span class="hljs-string">"The Great Gatsby"</span>;
        myBook.author = <span class="hljs-string">"F. Scott Fitzgerald"</span>;

        <span class="hljs-comment">// Displaying the book's details</span>
        myBook.showBookInfo();
    }
}
</code></pre>
<p><strong>Solution to Challenge 2: Intermediate – Working with Default Constructors</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> </span>{
    String title;
    String author;

    <span class="hljs-comment">// Default constructor initializing the attributes to "Unknown"</span>
    Book() {
        title = <span class="hljs-string">"Unknown"</span>;
        author = <span class="hljs-string">"Unknown"</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showBookInfo</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Title: "</span> + title + <span class="hljs-string">", Author: "</span> + author);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Instantiating the class without passing any arguments</span>
        Book unknownBook = <span class="hljs-keyword">new</span> Book();
        unknownBook.showBookInfo();  <span class="hljs-comment">// This will print: Title: Unknown, Author: Unknown</span>
    }
}
</code></pre>
<p><strong>Solution to Challenge 3: Intermediate – Introducing Parameterized Constructors</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> </span>{
    String title;
    String author;

    <span class="hljs-comment">// Parameterized constructor accepting title and author</span>
    Book(String t, String a) {
        title = t;
        author = a;
    }

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showBookInfo</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Title: "</span> + title + <span class="hljs-string">", Author: "</span> + author);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Instantiating the class with specific details</span>
        Book specificBook = <span class="hljs-keyword">new</span> Book(<span class="hljs-string">"1984"</span>, <span class="hljs-string">"George Orwell"</span>);
        specificBook.showBookInfo();  <span class="hljs-comment">// This will print: Title: 1984, Author: George Orwell</span>
    }
}
</code></pre>
<p><strong>Solution to Challenge 4: Advanced – Constructor Overloading</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> </span>{
    String title;
    String author;

    Book() {
        title = <span class="hljs-string">"Unknown"</span>;
        author = <span class="hljs-string">"Unknown"</span>;
    }

    Book(String t) {
        title = t;
        author = <span class="hljs-string">"Unknown"</span>;
    }

    Book(String t, String a) {
        title = t;
        author = a;
    }

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showBookInfo</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Title: "</span> + title + <span class="hljs-string">", Author: "</span> + author);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Book onlyTitle = <span class="hljs-keyword">new</span> Book(<span class="hljs-string">"Brave New World"</span>);
        onlyTitle.showBookInfo();  <span class="hljs-comment">// This will print: Title: Brave New World, Author: Unknown</span>

        Book fullDetails = <span class="hljs-keyword">new</span> Book(<span class="hljs-string">"The Hobbit"</span>, <span class="hljs-string">"J.R.R. Tolkien"</span>);
        fullDetails.showBookInfo();  <span class="hljs-comment">// This will print: Title: The Hobbit, Author: J.R.R. Tolkien</span>
    }
}
</code></pre>
<p><strong>Solution to Challenge 5: Expert – <code>this</code> Keyword in Action</strong></p>
<pre><code class="lang-java">javaCopy code
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Book</span> </span>{
    String title;
    String author;

    Book(String title, String author) {
        <span class="hljs-keyword">this</span>.title = title;  <span class="hljs-comment">// 'this' keyword differentiates instance variable from parameter</span>
        <span class="hljs-keyword">this</span>.author = author;
    }

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">showBookInfo</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Title: "</span> + title + <span class="hljs-string">", Author: "</span> + author);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Book exampleBook = <span class="hljs-keyword">new</span> Book(<span class="hljs-string">"Moby Dick"</span>, <span class="hljs-string">"Herman Melville"</span>);
        exampleBook.showBookInfo();  <span class="hljs-comment">// This will print: Title: Moby Dick, Author: Herman Melville</span>
    }
}
</code></pre>
<p><strong>Solution to Challenge 6: Super Expert – Analyze Constructor Flow</strong></p>
<p>The given code will print:</p>
<pre><code>Parent Constructor
Child Constructor
</code></pre><p>This is because the parent class constructor gets executed before the child class constructor.</p>
<p>For the third part of the challenge:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parent</span> </span>{
    Parent(<span class="hljs-keyword">int</span> a) {
        System.out.println(<span class="hljs-string">"Parent Constructor with parameter: "</span> + a);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Parent</span> </span>{
    Child(<span class="hljs-keyword">int</span> b) {
        <span class="hljs-keyword">super</span>(b);  <span class="hljs-comment">// Calling the parent's parameterized constructor</span>
        System.out.println(<span class="hljs-string">"Child Constructor with parameter: "</span> + b);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConstructorFlow</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Child obj = <span class="hljs-keyword">new</span> Child(<span class="hljs-number">5</span>);
    }
}
</code></pre>
<p>This will print:</p>
<pre><code class="lang-sql">sqlCopy code
Parent Constructor <span class="hljs-keyword">with</span> parameter: <span class="hljs-number">5</span>
<span class="hljs-keyword">Child</span> <span class="hljs-keyword">Constructor</span> <span class="hljs-keyword">with</span> parameter: <span class="hljs-number">5</span>
</code></pre>
<p>These solutions provide practical insight into the mentioned challenges, giving you a detailed understanding of the respective concepts.</p>
<h3 id="heading-what-is-inheritance-in-object-oriented-programming">What is Inheritance in Object-Oriented Programming?</h3>
<p>Understanding inheritance is key to becoming an adept Java developer. Inheritance allows a class to acquire properties and methods belonging to another class through inheritance, creating code reusability as well as hierarchical relationships among classes.</p>
<p>At its heart, inheritance resembles real-world inheritance: just as children inherit traits from their parents in real life, Java classes inherit features and methods from their parent classes as inheritance.</p>
<h4 id="heading-advantages-of-using-inheritance">Advantages of using Inheritance</h4>
<ol>
<li>Code Reusability: Avoid redundant code by inheriting functionalities from the parent class.</li>
<li>Enhanced Readability: Hierarchical structures give a clearer, more intuitive view of related classes.</li>
<li>Improved Maintainability: Change the parent class, and the child classes get updated accordingly.</li>
</ol>
<h4 id="heading-the-extends-keyword">The <code>extends</code> keyword</h4>
<p>In Java, inheritance refers to a process by which one class inherits properties (attributes and methods) from another. A key feature of inheritance in this context is the <code>extends</code> keyword. It marks out hierarchical relationships between classes in an effort to streamline code, enhance reusability and establish clear lineage among related classes.</p>
<p>When a class inherits from another, two main roles are defined:</p>
<ol>
<li><strong>Superclass (or Parent Class):</strong> This class acts as the source for inheritance. Its blueprint forms the basis from which subsequent classes inherit attributes or methods from.</li>
<li><strong>Subclass (or Child class):</strong> This is the class that does the inheriting. It will naturally incorporate all non-private properties and methods from its superclass and can also have additional properties and methods of its own.</li>
</ol>
<p>As an example, consider the Vehicle class with attributes and methods like color and start(). </p>
<p>If we wanted to create more specific classes such as Car instead of recreating everything from scratch, instead we can have Car extend Vehicle. It would then automatically include its color attribute, start() method as well as possible specific attributes like numberOfDoors for this example Car class.</p>
<h4 id="heading-basic-inheritance">Basic Inheritance</h4>
<ul>
<li><strong>Parent and Subclass Relations:</strong> Central to inheritance is the relationship between parent and child classes. For instance, inheritor subclass inherits all accessible attributes and methods from its superclass. This creates a clear lineage from one class to the other – for instance all physicians fall under Human's subclass but not all humans fall within Doctor.</li>
<li><strong>Utilizing Attributes and Methods from the Parent Class:</strong> When inheriting from a parent class, its attributes and methods become accessible (with some access-level restrictions). This means that when used directly without having to redefine them first. Also, inheritant classes can extend or override these properties for their unique requirements.</li>
</ul>
<p>Real-world example to illustrate this idea: Consider an experienced artist. Their apprentice doesn't begin their learning from scratch – rather, leveraging foundational skills taught by their artist (superclass), they then add their unique flair, creating their masterpiece (subclass).</p>
<p>Exercise:</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
    String name;
    String species;

    <span class="hljs-comment">// Constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Animal</span><span class="hljs-params">(String name, String species)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
        <span class="hljs-keyword">this</span>.species = species;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-comment">// Constructor</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Dog</span><span class="hljs-params">(String name, String species)</span> </span>{
        <span class="hljs-keyword">super</span>(name, species);
    }

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">bark</span><span class="hljs-params">()</span> </span>{
        System.out.println(name + <span class="hljs-string">" is barking!"</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Dog myDog = <span class="hljs-keyword">new</span> Dog(<span class="hljs-string">"Buddy"</span>, <span class="hljs-string">"Golden Retriever"</span>);
        System.out.println(myDog.name);  <span class="hljs-comment">// Outputs: Buddy</span>
        System.out.println(myDog.species);  <span class="hljs-comment">// Outputs: Golden Retriever</span>
        myDog.bark();  <span class="hljs-comment">// Outputs: Buddy is barking!</span>
    }
}
</code></pre>
<p><strong>Method Overriding:</strong> Method overriding allows a subclass to provide its unique version of a method already defined in its superclass. For instance, a <code>Bird</code> superclass might have a method <code>sound()</code>, which returns "Bird makes a sound". A <code>Sparrow</code> subclass can override this to return "Sparrow chirps", reflecting its specific behavior.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bird</span> </span>{
    <span class="hljs-comment">// Method in the superclass</span>
    <span class="hljs-function">String <span class="hljs-title">sound</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Bird makes a sound"</span>;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Sparrow</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Bird</span> </span>{
    <span class="hljs-comment">// Overriding the method from superclass</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function">String <span class="hljs-title">sound</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-string">"Sparrow chirps"</span>;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OverrideExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Sparrow mySparrow = <span class="hljs-keyword">new</span> Sparrow();
        System.out.println(mySparrow.sound());  <span class="hljs-comment">// This will print "Sparrow chirps"</span>
    }
}
</code></pre>
<p><strong>Method Overloading vs. Method Overriding:</strong> Method overloading lets a class have several methods with the same name but different parameters, allowing varied actions based on parameters. </p>
<p>In contrast, method overriding enables a subclass to offer a distinct behavior for an inherited method.</p>
<p>For instance, a <code>Calculator</code> might have overloaded <code>add()</code> methods for two or three integers, whereas a subclass <code>ScientificCalculator</code> could override the <code>sqrt()</code> method to modify its behavior.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span> </span>{
    <span class="hljs-comment">// Method overloading - same method name with different parameters</span>
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>{
        <span class="hljs-keyword">return</span> a + b;
    }

    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b, <span class="hljs-keyword">int</span> c)</span> </span>{
        <span class="hljs-keyword">return</span> a + b + c;
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ScientificCalculator</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Calculator</span> </span>{
    <span class="hljs-comment">// Overriding the method to modify its behavior in the subclass</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>{
        <span class="hljs-keyword">return</span> a + b + <span class="hljs-number">10</span>;  <span class="hljs-comment">// Just for illustration: adding 10 to the result</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OverloadOverrideExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        ScientificCalculator myCalc = <span class="hljs-keyword">new</span> ScientificCalculator();
        System.out.println(myCalc.add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>));       <span class="hljs-comment">// This will print 18 because of the overridden method</span>
        System.out.println(myCalc.add(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>, <span class="hljs-number">2</span>));   <span class="hljs-comment">// This will print 10 because of method overloading</span>
    }
}
</code></pre>
<p><strong>The <code>@Override</code> Annotation:</strong> The <code>@Override</code> annotation in Java indicates that a method is meant to override one in its superclass. It's a safeguard, ensuring that the overriding is intentional and correctly done, helping catch errors during compile time.</p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Printer</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Printing from base class"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LaserPrinter</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Printer</span> </span>{
    <span class="hljs-comment">// Using the @Override annotation to signify intention to override</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Laser printing in progress"</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OverrideAnnotationExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        LaserPrinter lp = <span class="hljs-keyword">new</span> LaserPrinter();
        lp.print();  <span class="hljs-comment">// This will print "Laser printing in progress"</span>
    }
}
</code></pre>
<h4 id="heading-constructors-in-inheritance">Constructors in Inheritance</h4>
<p><strong>Chain of Constructor Calls:</strong> Whenever an object of a subclass is instantiated, its constructor does not just run in isolation. Instead, a series of constructor calls are initiated that traverse from topmost superclass down to actual subclass being instantiated.</p>
<p>Imagine having a hierarchy composed of Grandparent, Parent (that extends Grandparent), and Child classes. When creating objects from this class (Child), its constructor will first call Grandparent's constructor before proceeding onward to Parent and then finally Child. This ensures the inheritance chain starts off correctly.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Grandparent</span> </span>{
    Grandparent() {
        System.out.println(<span class="hljs-string">"Grandparent's constructor called."</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parent</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Grandparent</span> </span>{
    Parent() {
        System.out.println(<span class="hljs-string">"Parent's constructor called."</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Parent</span> </span>{
    Child() {
        System.out.println(<span class="hljs-string">"Child's constructor called."</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ConstructorChainExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">new</span> Child();  <span class="hljs-comment">// This will print messages from all three constructors in the order: Grandparent, Parent, Child</span>
    }
}
</code></pre>
<p><strong>Use of <code>super()</code> to Call Parent Class Constructor:</strong> In Java, <code>super()</code> can be used within subclass constructors to call their parent class's constructor. By default, Java will insert an indirect call for you via no-argument <code>super</code>. When there's an optional parameterized constructor it's essential that <code>super</code> be called with its exact arguments to invoke its constructor correctly.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java">javaCopy code
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Parent</span> </span>{
    Parent(String message) {
        System.out.println(message);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Child</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Parent</span> </span>{
    Child() {
        <span class="hljs-keyword">super</span>(<span class="hljs-string">"Parent's constructor called with a message."</span>);  <span class="hljs-comment">// Explicitly calling parent's constructor with a message</span>
        System.out.println(<span class="hljs-string">"Child's constructor called."</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SuperExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">new</span> Child();  <span class="hljs-comment">// This will print both messages: one from the Parent's constructor and one from the Child's constructor</span>
    }
}
</code></pre>
<p>As shown above, the Child class's constructor explicitly calls its parent class's constructor using <code>super()</code> with all required arguments passed as parameters.</p>
<h4 id="heading-how-to-access-superclass-methods">How to Access Superclass Methods</h4>
<p>Let's now see the <code>super</code> keyword in action.</p>
<p>Consider a scenario where we have a <code>Vehicle</code> class with a method <code>description()</code>, and a <code>Car</code> class that extends <code>Vehicle</code>. The <code>Car</code> class wants to provide additional details in the description but also wants to keep the basic details provided by the <code>Vehicle</code> class. This is where <code>super</code> comes into play.</p>
<p><strong>Example:</strong></p>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Vehicle</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">description</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"This is a generic vehicle."</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Vehicle</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">description</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">super</span>.description();  <span class="hljs-comment">// Calling the parent class's description method</span>
        System.out.println(<span class="hljs-string">"More specifically, this is a car."</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SuperUsageExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Car car = <span class="hljs-keyword">new</span> Car();
        car.description();
        <span class="hljs-comment">// Output:</span>
        <span class="hljs-comment">// This is a generic vehicle.</span>
        <span class="hljs-comment">// More specifically, this is a car.</span>
    }
}
</code></pre>
<p>In the above example, the <code>Car</code> class's <code>description()</code> method first calls the <code>Vehicle</code> class's <code>description()</code> method using <code>super.description()</code>. After that, it adds its own specific message. This allows the <code>Car</code> class to reuse the general description from the <code>Vehicle</code> class and then provide additional details that are specific to cars.</p>
<h4 id="heading-multiple-inheritance">Multiple Inheritance</h4>
<pre><code class="lang-java">
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">displayPersonDetails</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Address</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">displayAddressDetails</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Contact</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Person</span>, <span class="hljs-title">Address</span> </span>{
    <span class="hljs-comment">// Define attributes for both interfaces and provide implementation for both methods</span>
    <span class="hljs-comment">// This exercise illustrates how one class can inherit from multiple interfaces.</span>
}
</code></pre>
<p>The above are just the first few key concepts from the Java Inheritance Masterclass. As we dive deeper into topics like abstract classes, polymorphism, protected members, and various forms of inheritance, remember that the aim is not just to grasp the syntax, but to deeply understand the foundational concepts. Only by internalizing these principles can you craft code that's both efficient and elegant. </p>
<h3 id="heading-what-is-polymorphism-in-object-oriented-programming">What is Polymorphism in Object-Oriented Programming?</h3>
<p>Polymorphism – from Greek words meaning many forms – is an indispensable concept in Object-Oriented Programming (OOP). It serves to ensure that all entities of different types behave similarly when interacting together, adding depth to OOP concepts like class hierarchy. </p>
<p>Polymorphism plays an essential part of Java's OOP language by providing seamless interactions among class entities. This results in rich OOP concepts that add greater dimension.</p>
<p>At its core, polymorphism enables us to view objects of diverse classes as instances of one superclass, creating adaptability within code. This flexibility helps facilitate better reusability. Common behavior can be easily inherited while deviations managed seamlessly. It also improves the readability of code while opening doors for scalable software solutions.</p>
<h4 id="heading-types-of-polymorphism">Types of Polymorphism</h4>
<ul>
<li><strong>Compile-time Polymorphism (Static Polymorphism)</strong>: This type of polymorphism is achieved when we overload a method.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a)</span> </span>{ ... }
<span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">(<span class="hljs-keyword">double</span> b)</span> </span>{ ... }
</code></pre>
<p>Here, the method's name remains the same, but the parameter lists vary – this distinction in parameters is known as method signatures.</p>
<ul>
<li><strong>Run-time Polymorphism (Dynamic Polymorphism)</strong>: This involves overriding methods from a superclass in its subclass.</li>
</ul>
<pre><code class="lang-java"><span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
   <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sound</span><span class="hljs-params">()</span> </span>{ ... }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
   <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sound</span><span class="hljs-params">()</span> </span>{ ... }
}
</code></pre>
<p>At runtime, Java uses the object's actual class (like Dog) to determine which version of an overridden method should execute.</p>
<h4 id="heading-casting-in-polymorphism">Casting in Polymorphism</h4>
<ul>
<li><strong>Upcasting</strong>: This involves casting an object to one of its superclass types. Being an implicit conversion, it's safe.</li>
</ul>
<pre><code class="lang-java">Dog myDog = <span class="hljs-keyword">new</span> Dog();
Animal myAnimal = myDog;  <span class="hljs-comment">// Upcasting</span>
</code></pre>
<ul>
<li><strong>Downcasting</strong>: Here, we cast an object to one of its subclass types. It must be done explicitly due to potential risks.</li>
</ul>
<pre><code class="lang-java">Animal myAnimal = <span class="hljs-keyword">new</span> Dog();
Dog myDog = (Dog) myAnimal;  <span class="hljs-comment">// Downcasting</span>
</code></pre>
<p>It's important to be cautious and make sure you do this correctly, as forced incorrect downcasting can lead to errors.</p>
<h4 id="heading-the-utility-of-the-instanceof-operator">The Utility of the <code>instanceof</code> Operator</h4>
<p>The <code>instanceof</code> operator is integral for type verification, often used before downcasting to prevent unwarranted <code>ClassCastException</code>.</p>
<pre><code class="lang-java"><span class="hljs-keyword">if</span> (myAnimal <span class="hljs-keyword">instanceof</span> Dog) {
   Dog myDog = (Dog) myAnimal;
</code></pre>
<p>By confirming type beforehand, we establish a safe environment for typecasting.</p>
<h4 id="heading-benefits-of-polymorphism">Benefits of Polymorphism</h4>
<ul>
<li><strong>Reusability</strong>: With Polymorphism, code components can be leveraged across multiple classes, curtailing redundancy.</li>
<li><strong>Extensibility</strong>: As business needs evolve, Polymorphism ensures minimal disruptions when expanding functionalities.</li>
<li><strong>Flexibility</strong>: Modules remain distinct, making systems more manageable.</li>
<li><strong>Simplified Design</strong>: Systems designed with Polymorphism are inherently organized and intuitive.</li>
<li><strong>Interchangeability</strong>: With Polymorphism, varying implementations can be switched seamlessly.</li>
<li><strong>Enhanced Maintainability</strong>: With standardized structures, tasks like debugging and updates become less cumbersome.</li>
</ul>
<h4 id="heading-practical-scenarios-and-use-cases">Practical Scenarios and Use-cases</h4>
<p>Polymorphism shines in various real-world applications. From GUI systems where different button types inherit from a generic button class, to database interactions where varied database entities are managed under a universal interface, or even gaming where different character classes derive from a primary character blueprint, its presence is undeniable. </p>
<p>Here are few examples to showcase polymorphism in action.</p>
<p><strong>Basic Example: Animal Sounds</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// The superclass Animal has a method sound(), which provides a generic implementation.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sound</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Animal makes a sound"</span>);
    }
}

<span class="hljs-comment">// Dog is a subclass of Animal and overrides the sound() method.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dog</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sound</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Dog barks"</span>);
    }
}

<span class="hljs-comment">// Cat is another subclass of Animal and also overrides the sound() method.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Cat</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Animal</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">sound</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Cat meows"</span>);
    }
}

<span class="hljs-comment">// This class demonstrates polymorphism.</span>
<span class="hljs-comment">// We're able to treat both Dog and Cat as Animal and call the sound() method.</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TestPolymorphism</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Animal a;  <span class="hljs-comment">// Reference variable of type Animal</span>

        a = <span class="hljs-keyword">new</span> Dog();  <span class="hljs-comment">// a now refers to a Dog object</span>
        a.sound();  <span class="hljs-comment">// Calls the Dog's overridden sound() method</span>

        a = <span class="hljs-keyword">new</span> Cat();  <span class="hljs-comment">// a now refers to a Cat object</span>
        a.sound();  <span class="hljs-comment">// Calls the Cat's overridden sound() method</span>
    }
}
</code></pre>
<p><strong>Intermediate Example: Payment Methods</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract class defining the contract for payment methods.</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentMethod</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span></span>;
}

<span class="hljs-comment">// CreditCard is a concrete subclass that provides an implementation of the pay() method.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CreditCard</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">PaymentMethod</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Paid $"</span> + amount + <span class="hljs-string">" using Credit Card."</span>);
    }
}

<span class="hljs-comment">// PayPal is another concrete subclass with its own implementation of pay().</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PayPal</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">PaymentMethod</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">pay</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        System.out.println(<span class="hljs-string">"Paid $"</span> + amount + <span class="hljs-string">" using PayPal."</span>);
    }
}

<span class="hljs-comment">// Demonstrates polymorphism by treating both CreditCard and PayPal as PaymentMethod.</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentTest</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        PaymentMethod p;  <span class="hljs-comment">// Reference of type PaymentMethod</span>

        p = <span class="hljs-keyword">new</span> CreditCard();  <span class="hljs-comment">// p now refers to a CreditCard object</span>
        p.pay(<span class="hljs-number">100.50</span>);  <span class="hljs-comment">// Calls CreditCard's implementation of pay()</span>

        p = <span class="hljs-keyword">new</span> PayPal();  <span class="hljs-comment">// p now refers to a PayPal object</span>
        p.pay(<span class="hljs-number">200.75</span>);  <span class="hljs-comment">// Calls PayPal's implementation of pay()</span>
    }
}
</code></pre>
<p><strong>Advanced Example: UI Elements &amp; Events</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Interface for elements that respond to click events.</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">OnClickListener</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Abstract superclass defining a contract for all UI elements.</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UIElement</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setOnClickListener</span><span class="hljs-params">(OnClickListener listener)</span></span>;
}

<span class="hljs-comment">// Button is a subclass of UIElement and also implements OnClickListener.</span>
<span class="hljs-comment">// Demonstrates multiple polymorphism (with both superclass and interface).</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Button</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">UIElement</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">OnClickListener</span> </span>{
    <span class="hljs-keyword">private</span> OnClickListener listener;

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Drawing a button..."</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setOnClickListener</span><span class="hljs-params">(OnClickListener listener)</span> </span>{
        <span class="hljs-keyword">this</span>.listener = listener;
    }

    <span class="hljs-comment">// Simulates a click event.</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">click</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">if</span>(listener != <span class="hljs-keyword">null</span>) {
            listener.onClick();
        }
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">onClick</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Button was clicked!"</span>);
    }
}

<span class="hljs-comment">// Dropdown is another subclass of UIElement.</span>
<span class="hljs-comment">// It can potentially implement OnClickListener but for brevity, it's omitted here.</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Dropdown</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">UIElement</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Drawing a dropdown..."</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setOnClickListener</span><span class="hljs-params">(OnClickListener listener)</span> </span>{
        <span class="hljs-comment">// Potential implementation for dropdown click.</span>
    }
}

<span class="hljs-comment">// Test class to demonstrate polymorphism in action, especially with interfaces.</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">UIElementTest</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Button btn = <span class="hljs-keyword">new</span> Button();
        btn.draw();
        btn.setOnClickListener(btn);  <span class="hljs-comment">// Setting the button itself as the click listener</span>
        btn.click();
    }
}
</code></pre>
<p>In these examples, polymorphism allows us to write code that treats objects of different classes as objects of a common superclass or interface. This gives flexibility, as demonstrated by the ability to easily switch between different subclass objects (for example, <code>Dog</code>, <code>Cat</code>, <code>CreditCard</code>, <code>PayPal</code>) using a common reference type (<code>Animal</code>, <code>PaymentMethod</code>).</p>
<h3 id="heading-what-is-encapsulation-in-object-oriented-programming">What is Encapsulation in Object-Oriented Programming?</h3>
<p>Among the foundational quartet of OOP principles, encapsulation primarily focuses on bundling the data and operations on that data into a single unit. This ensures that objects maintain their integrity by preventing unauthorized access and modifications. </p>
<p>Beyond just a programming technique, encapsulation is indispensable in fostering secure coding practices and achieving a modular software design.</p>
<h4 id="heading-how-encapsulation-works">How Encapsulation Works</h4>
<p>At its core, encapsulation is about data protection and controlled access. It can be analogized as a protective shell that guards the delicate internal workings of a system. </p>
<p>Consider a watch: while users can see the time and adjust settings using knobs, the intricate machinery inside remains hidden, safeguarding its functionality.</p>
<h4 id="heading-how-to-implement-encapsulation">How to Implement Encapsulation</h4>
<p>Java provides us with access modifiers to enforce encapsulation. The most restrictive of these is <code>private</code>, ensuring that class members are only accessible within that class. By declaring variables as private, we can shield them from unintended external interference.</p>
<pre><code class="lang-java"><span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getAge</span><span class="hljs-params">()</span> </span>{
    <span class="hljs-keyword">return</span> age;
}

<span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAge</span><span class="hljs-params">(<span class="hljs-keyword">int</span> age)</span> </span>{
    <span class="hljs-keyword">if</span> (age &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">this</span>.age = age;
    }
}
</code></pre>
<p>In the above code, encapsulation ensures that <code>age</code> can never be set to a negative value.</p>
<h4 id="heading-benefits-of-encapsulation">Benefits of Encapsulation</h4>
<p><strong>Control</strong>: Using encapsulation, we can add conditions to control how data is accessed or modified.</p>
<pre><code class="lang-java">
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Account</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> balance;

    <span class="hljs-comment">// Getter method for balance</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">getBalance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> balance;
    }

    <span class="hljs-comment">// Setter method to control the deposit operation</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deposit</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        <span class="hljs-keyword">if</span> (amount &gt; <span class="hljs-number">0</span>) {
            balance += amount;
        } <span class="hljs-keyword">else</span> {
            System.out.println(<span class="hljs-string">"Invalid deposit amount!"</span>);
        }
    }

    <span class="hljs-comment">// Setter method to control the withdraw operation</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">withdraw</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        <span class="hljs-keyword">if</span> (amount &gt; <span class="hljs-number">0</span> &amp;&amp; amount &lt;= balance) {
            balance -= amount;
        } <span class="hljs-keyword">else</span> {
            System.out.println(<span class="hljs-string">"Invalid withdrawal amount!"</span>);
        }
    }
}
</code></pre>
<p><strong>Flexibility and Maintenance</strong>: By encapsulating data, any internal changes to a class won't directly affect its interactions with other classes.</p>
<pre><code class="lang-java">
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Vehicle</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> speed;

    <span class="hljs-comment">// Now, if we decide to measure speed in terms of mph instead of kph in the future,</span>
    <span class="hljs-comment">// we just have to change this class without affecting classes that use `Vehicle`.</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getSpeedInMph</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> speed * <span class="hljs-number">5</span>/<span class="hljs-number">8</span>; <span class="hljs-comment">// converting kph to mph</span>
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSpeed</span><span class="hljs-params">(<span class="hljs-keyword">int</span> speed)</span> </span>{
        <span class="hljs-keyword">this</span>.speed = speed;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Race</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">startRace</span><span class="hljs-params">(Vehicle v1, Vehicle v2)</span> </span>{
        <span class="hljs-comment">// Uses Vehicle class but is not dependent on how Vehicle internally represents speed.</span>
        <span class="hljs-keyword">int</span> diff = v1.getSpeedInMph() - v2.getSpeedInMph();
        System.out.println(<span class="hljs-string">"Speed difference is: "</span> + diff + <span class="hljs-string">" mph"</span>);
    }
}
</code></pre>
<p><strong>Increased Security</strong>: Shielding class members and only allowing them to be changed through controlled methods ensures security.</p>
<pre><code class="lang-java">
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PasswordManager</span> </span>{
    <span class="hljs-keyword">private</span> String encryptedPassword;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setPassword</span><span class="hljs-params">(String password)</span> </span>{
        <span class="hljs-comment">// Assuming encrypt() is a method that encrypts the password.</span>
        <span class="hljs-keyword">this</span>.encryptedPassword = encrypt(password);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">boolean</span> <span class="hljs-title">validatePassword</span><span class="hljs-params">(String password)</span> </span>{
        <span class="hljs-keyword">return</span> encrypt(password).equals(encryptedPassword);
    }

    <span class="hljs-function"><span class="hljs-keyword">private</span> String <span class="hljs-title">encrypt</span><span class="hljs-params">(String data)</span> </span>{
        <span class="hljs-comment">// Encryption logic here</span>
        <span class="hljs-keyword">return</span> <span class="hljs-comment">/* encrypted data */</span>;
    }
}
</code></pre>
<p><strong>Modular Approach</strong>: Encapsulation allows a system to be split into clear, well-defined modules, which can then be developed and maintained separately.</p>
<pre><code class="lang-java">
<span class="hljs-comment">// User module</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">User</span> </span>{
    <span class="hljs-keyword">private</span> String name;
    <span class="hljs-keyword">private</span> String email;

    <span class="hljs-comment">// getters and setters</span>
}

<span class="hljs-comment">// Product module</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Product</span> </span>{
    <span class="hljs-keyword">private</span> String productId;
    <span class="hljs-keyword">private</span> String description;

    <span class="hljs-comment">// getters and setters</span>
}

<span class="hljs-comment">// Billing module</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Invoice</span> </span>{
    <span class="hljs-keyword">private</span> User user;
    <span class="hljs-keyword">private</span> Product product;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> amount;

    <span class="hljs-comment">// getters and setters</span>
}
</code></pre>
<p>Each of these modules (User, Product, Invoice) can be developed, expanded, or maintained independently of the others.</p>
<h4 id="heading-real-world-analogy-of-encapsulation">Real-world Analogy of Encapsulation</h4>
<p>Imagine a bank account system. Account holders can deposit, withdraw, and check their balance, but the detailed mechanics of how the bank processes these requests remain concealed. </p>
<p>Just as the bank hides the intricacies of its operations while exposing essential functionalities, encapsulation in programming hides the details while providing necessary operations.</p>
<h4 id="heading-advanced-encapsulation-concepts">Advanced Encapsulation Concepts</h4>
<p>Creating immutable classes ensures that once an object is created, it cannot be altered. This is achieved by making all members final and providing no setters.</p>
<p>The <code>final</code> keyword can also restrict inheritance and prevent method overriding, adding another layer of encapsulation.</p>
<p>While encapsulation focuses on bundling data and its operations, abstraction, another OOP principle, emphasizes hiding complex implementations and exposing only relevant features. Although intertwined, they serve distinct roles.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Creating immutable class in Java using final keyword</span>
<span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ImmutableClass</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">final</span> String name;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">ImmutableClass</span><span class="hljs-params">(String name)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getName</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> name;
    }

    <span class="hljs-comment">// No setter methods – this makes the class immutable</span>
}

<span class="hljs-comment">// Using final keyword to prevent method overriding</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ParentClass</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">final</span> <span class="hljs-keyword">void</span> <span class="hljs-title">showFinalMethod</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"This is a final method from ParentClass"</span>);
    }
}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ChildClass</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">ParentClass</span> </span>{
    <span class="hljs-comment">// Attempting to override the final method from parent class would result in a compile-time error</span>
    <span class="hljs-comment">// public void showFinalMethod() {</span>
    <span class="hljs-comment">//     System.out.println("Trying to override final method");</span>
    <span class="hljs-comment">// }</span>
}
</code></pre>
<p>In the above code:</p>
<ul>
<li>The <code>ImmutableClass</code> is an example of an immutable class. Once an <code>ImmutableClass</code> object is created, its <code>name</code> property can't be changed because there's no setter method.</li>
<li>In the <code>ParentClass</code> and <code>ChildClass</code> example, the <code>showFinalMethod</code> in <code>ParentClass</code> is declared as <code>final</code>, so it can't be overridden in <code>ChildClass</code>.</li>
</ul>
<h4 id="heading-common-mistakes-and-pitfalls">Common Mistakes and Pitfalls</h4>
<p><strong>Failing to validate data in setter methods can lead to inconsistencies</strong>. Consider a <code>Person</code> class with an <code>age</code> field. We should validate data in the setter method to ensure the <code>age</code> can't be set to a negative value.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> age;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setAge</span><span class="hljs-params">(<span class="hljs-keyword">int</span> age)</span> </span>{
        <span class="hljs-keyword">if</span>(age &lt; <span class="hljs-number">0</span>) {
            System.out.println(<span class="hljs-string">"Age can't be negative."</span>);
        } <span class="hljs-keyword">else</span> {
            <span class="hljs-keyword">this</span>.age = age;
        }
    }
}
</code></pre>
<p><strong>Overexposing class details dilutes the essence of encapsulation.</strong> If we have a <code>BankAccount</code> class with a <code>balance</code> field, we shouldn't expose this detail directly. Instead, we can provide public methods to deposit, withdraw and check the balance.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BankAccount</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> balance;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deposit</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        <span class="hljs-keyword">if</span>(amount &gt; <span class="hljs-number">0</span>) {
            balance += amount;
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">withdraw</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> </span>{
        <span class="hljs-keyword">if</span>(amount &gt; <span class="hljs-number">0</span> &amp;&amp; amount &lt;= balance) {
            balance -= amount;
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">checkBalance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> balance;
    }
}
</code></pre>
<p><strong>Underutilizing or misusing access modifiers can compromise data integrity.</strong> If we have a <code>Car</code> class with <code>speed</code> field, we should declare it as <code>private</code> to prevent uncontrolled access. We can then provide public getter and setter methods to control how <code>speed</code> is accessed and modified.</p>
<pre><code class="lang-java"><span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">int</span> speed;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">getSpeed</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> speed;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSpeed</span><span class="hljs-params">(<span class="hljs-keyword">int</span> speed)</span> </span>{
        <span class="hljs-keyword">if</span>(speed &gt;= <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">this</span>.speed = speed;
        }
    }
}
</code></pre>
<h4 id="heading-practical-scenarios-and-use-cases-1">Practical Scenarios and Use-cases</h4>
<p>Encapsulation finds its mettle in:</p>
<ul>
<li>Crafting secure login systems where users' credentials are shielded.</li>
<li>Building configuration managers for applications where system settings are protected yet adjustable.</li>
<li>Designing settings or preferences modules in software where users can personalize their experience while core configurations remain intact.</li>
</ul>
<h3 id="heading-what-is-abstraction-in-object-oriented-programming">What is Abstraction in Object-Oriented Programming?</h3>
<p>Abstraction in object-oriented programming (OOP) is an integral component that allows developers to streamline complex systems while keeping focus on essential details. Abstraction involves extracting relevant data while hiding irrelevant implementation details.</p>
<p>Abstraction allows developers to build models of real-world objects, systems or processes by abstracting away complexity while only exposing essential characteristics. This helps create more manageable and understandable code in turn.</p>
<p>Abstraction can help with designing modular and maintainable software by providing a clear separation between internal implementation and outside world.</p>
<p>Developers can then define abstract classes and interfaces which serve as blueprints to create objects properly while assuring smooth implementation of objects created through abstraction.</p>
<p>Abstractions enable us to work at a deeper level of comprehension by concentrating on essential behaviors and functionalities rather than getting bogged down in details. By harnessing abstraction, developers can easily craft clean code which is easy for others to read, understand, and maintain.</p>
<p>Abstraction plays an instrumental role in helping developers to effectively manage complexity and develop applications that comply with object-oriented programming principles.</p>
<h4 id="heading-the-significance-of-abstraction-in-oop">The Significance of Abstraction in OOP</h4>
<p>Abstraction plays an essential role in object-oriented programming (OOP), helping developers craft modular and maintainable code. By emphasizing essential details while concealing unnecessary ones, abstraction enables system designers to easily design their solutions while keeping implementation costs manageable. </p>
<p>Now, we'll explore this aspect further while emphasizing its role in developing code which is both scalable and adaptable.</p>
<h4 id="heading-creating-modular-code">Creating Modular Code</h4>
<p>Abstracting allows developers to break complex systems down into manageable modules for easier understanding and updating of codebases. </p>
<p>By abstracting away underlying implementation details, designers can focus more on designing user-friendly interfaces while also reusing code components across their software suite. This improves readability, maintainability and scalability in general.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract Module class</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Module</span> </span>{
    <span class="hljs-comment">// Abstract method to perform module-specific functionality</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">performAction</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Concrete LoginModule</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">LoginModule</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Module</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">performAction</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"LoginModule: User logged in successfully."</span>);
        <span class="hljs-comment">// Add login logic here</span>
    }
}

<span class="hljs-comment">// Concrete PaymentModule</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PaymentModule</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Module</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">performAction</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"PaymentModule: Payment processed."</span>);
        <span class="hljs-comment">// Add payment processing logic here</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ModularCodeExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of modules</span>
        Module loginModule = <span class="hljs-keyword">new</span> LoginModule();
        Module paymentModule = <span class="hljs-keyword">new</span> PaymentModule();

        <span class="hljs-comment">// Perform actions using the modules</span>
        loginModule.performAction(); <span class="hljs-comment">// Perform login</span>
        paymentModule.performAction(); <span class="hljs-comment">// Process payment</span>
    }
}
</code></pre>
<pre><code class="lang-java">LoginModule: User logged in successfully.
PaymentModule: Payment processed.
</code></pre>
<p>In this code:</p>
<ul>
<li>We introduce an abstract class <code>Module</code>, with an abstract method <code>performAction()</code> that represents the idea of a module without providing details about its implementation.</li>
<li><code>LoginModule</code> and <code>PaymentModule</code>, two concrete classes that extend <code>Module</code>, each contain specific implementations of its <code>performAction()</code> method to represent various modules within our software system.</li>
<li>In the <code>main()</code> method, we create instances of <code>LoginModule</code> and <code>PaymentModule</code> which encase login and payment functionality, respectively.</li>
<li>After creating these instances, we invoke their <code>performAction()</code> methods in order to carry out their actions.</li>
</ul>
<p>This example demonstrates how abstraction allows us to write modular code by defining a clear interface (<code>Module</code>), then implementing specific functionalities as separate modules (<code>LoginModule</code> and <code>PaymentModule</code>). This approach increases readability, maintainability and scalability by compartmentalizing functions within each module.</p>
<h4 id="heading-encapsulating-complexity">Encapsulating Complexity</h4>
<p>Abstraction helps in encapsulating complexity by separating the high-level behavior from the intricate implementation details. By defining abstract classes and methods, developers can specify common behavior and provide a clear interface for interacting with the underlying system. </p>
<p>This level of abstraction allows for the development of more flexible and extensible software, facilitating easier modification and updates.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract Shape class defining common behavior</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-comment">// Abstract method to calculate the area of the shape</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Concrete Circle class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }
}

<span class="hljs-comment">// Concrete Rectangle class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> width;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> width * height;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractionExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of shapes</span>
        Shape circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>);
        Shape rectangle = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">4.0</span>, <span class="hljs-number">6.0</span>);

        <span class="hljs-comment">// Calculate and display the areas</span>
        System.out.println(<span class="hljs-string">"Area of Circle: "</span> + circle.calculateArea());
        System.out.println(<span class="hljs-string">"Area of Rectangle: "</span> + rectangle.calculateArea());
    }
}
</code></pre>
<pre><code class="lang-java">Area of Circle: <span class="hljs-number">78.53981633974483</span>
Area of Rectangle: <span class="hljs-number">24.0</span>
</code></pre>
<p>In this code:</p>
<ul>
<li>We define an abstract class <code>Shape</code> with an abstract method <code>calculateArea()</code>. This abstract class represents the concept of a shape without specifying its implementation details.</li>
<li>We create two concrete classes, <code>Circle</code> and <code>Rectangle</code>, that extend the <code>Shape</code> class. These concrete classes provide specific implementations of the <code>calculateArea()</code> method, representing different shapes (circle and rectangle).</li>
<li>In the <code>main()</code> method, we create instances of <code>Circle</code> and <code>Rectangle</code>, which encapsulate the specific shapes and their dimensions.</li>
<li>We invoke the <code>calculateArea()</code> method on each shape to calculate and display their respective areas.</li>
</ul>
<p>This example demonstrates how abstraction allows us to encapsulate complexity by defining a clear interface (<code>Shape</code>) and implementing specific behavior for different shapes (<code>Circle</code> and <code>Rectangle</code>). </p>
<p>The level of abstraction provided by the <code>Shape</code> class enables the development of flexible and extensible software, making it easier to modify and update the code for new shapes or changes in behavior.</p>
<h4 id="heading-promoting-code-reusability">Promoting Code Reusability</h4>
<p>One of the major advantages of abstraction is code reuse. By creating abstract classes with common behaviors and inheriting them into subclasses, developers can build a basis that can be reused across several subclasses quickly. This saves both time and effort during development processes while creating consistency in software applications by standardizing common practices.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract Vehicle class defining common behavior</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Vehicle</span> </span>{
    <span class="hljs-keyword">private</span> String make;
    <span class="hljs-keyword">private</span> String model;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Vehicle</span><span class="hljs-params">(String make, String model)</span> </span>{
        <span class="hljs-keyword">this</span>.make = make;
        <span class="hljs-keyword">this</span>.model = model;
    }

    <span class="hljs-comment">// Abstract method for starting the vehicle</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">start</span><span class="hljs-params">()</span></span>;

    <span class="hljs-comment">// Abstract method for stopping the vehicle</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">stop</span><span class="hljs-params">()</span></span>;

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getMake</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> make;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> String <span class="hljs-title">getModel</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> model;
    }
}

<span class="hljs-comment">// Concrete Car class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Car</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Vehicle</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Car</span><span class="hljs-params">(String make, String model)</span> </span>{
        <span class="hljs-keyword">super</span>(make, model);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">start</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Car started."</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">stop</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Car stopped."</span>);
    }
}

<span class="hljs-comment">// Concrete Motorcycle class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Motorcycle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Vehicle</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Motorcycle</span><span class="hljs-params">(String make, String model)</span> </span>{
        <span class="hljs-keyword">super</span>(make, model);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">start</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Motorcycle started."</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">stop</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Motorcycle stopped."</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">CodeReuseExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of vehicles</span>
        Vehicle car = <span class="hljs-keyword">new</span> Car(<span class="hljs-string">"Toyota"</span>, <span class="hljs-string">"Camry"</span>);
        Vehicle motorcycle = <span class="hljs-keyword">new</span> Motorcycle(<span class="hljs-string">"Honda"</span>, <span class="hljs-string">"CBR 1000RR"</span>);

        <span class="hljs-comment">// Start and stop the vehicles</span>
        car.start();
        car.stop();

        motorcycle.start();
        motorcycle.stop();
    }
}
</code></pre>
<pre><code class="lang-java">Car started.
Car stopped.
Motorcycle started.
Motorcycle stopped.
</code></pre>
<h4 id="heading-enabling-future-extensibility">Enabling Future Extensibility</h4>
<p>Abstraction allows developers to construct software systems that are easily extensible. Utilizing abstract classes and interfaces, developers can design code to be open to future modifications and additions without disrupting existing codebases or disrupting future requirements. Abstraction thus contributes to long-term software project maintainability and sustainability.</p>
<p><strong>Version 1 (Before Extension):</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract Shape class representing a basic shape</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Concrete Circle class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }
}

<span class="hljs-comment">// Concrete Rectangle class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> width;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> width * height;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractionExampleBeforeExtension</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Circle circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>);
        Rectangle rectangle = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">4.0</span>, <span class="hljs-number">6.0</span>);

        System.out.println(<span class="hljs-string">"Area of Circle: "</span> + circle.calculateArea());
        System.out.println(<span class="hljs-string">"Area of Rectangle: "</span> + rectangle.calculateArea());
    }
}
</code></pre>
<p>In this version, we have a basic shape handling system with abstraction. It includes a <code>Shape</code> abstract class with concrete subclasses <code>Circle</code> and <code>Rectangle</code>.</p>
<p><strong>Version 2 (After Extension):</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract Shape class representing a basic shape</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Concrete Circle class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }
}

<span class="hljs-comment">// Concrete Rectangle class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> width;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> width * height;
    }
}

<span class="hljs-comment">// Concrete Triangle class (new shape added)</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Triangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> base;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Triangle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> base, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.base = base;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">0.5</span> * base * height;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractionExampleAfterExtension</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Circle circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>);
        Rectangle rectangle = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">4.0</span>, <span class="hljs-number">6.0</span>);
        Triangle triangle = <span class="hljs-keyword">new</span> Triangle(<span class="hljs-number">3.0</span>, <span class="hljs-number">4.0</span>);

        System.out.println(<span class="hljs-string">"Area of Circle: "</span> + circle.calculateArea());
        System.out.println(<span class="hljs-string">"Area of Rectangle: "</span> + rectangle.calculateArea());
        System.out.println(<span class="hljs-string">"Area of Triangle: "</span> + triangle.calculateArea());
    }
}
</code></pre>
<p>In this version, we have extended the system by adding a new concrete class <code>Triangle</code> representing a new shape. We did this without modifying the existing code, thanks to the use of abstraction. </p>
<p>This demonstrates how abstraction enables extensibility and the seamless integration of new features without disrupting existing code.</p>
<p>By encapsulating complexity, promoting code reusability, and enabling future extensibility, abstraction enhances the overall efficiency of the development process. Embracing abstraction in software design empowers developers to create scalable and adaptable systems that meet the evolving needs of users and businesses.</p>
<h2 id="heading-chapter-5-advanced-java-concepts">Chapter 5: Advanced Java Concepts</h2>
<p>As we embark on Chapter 5, we delve into the more advanced territories of Java programming, drawing upon the foundational knowledge established in previous chapters. </p>
<p>The concepts covered thus far — from the first foray into Java programs, through the nuances of data types, variables, and type casting, to the logical gymnastics of operators and control statements, and the object-oriented paradigms introduced in Chapter 4 — all converge to equip us for this deeper exploration.</p>
<p>In this chapter, we will dissect the sophisticated mechanisms of interfaces and abstract classes which are pivotal in designing flexible and scalable code. </p>
<p>We'll demystify abstract methods, which serve as contractual blueprints for subclasses, and explore interfaces, which allow us to create plug-and-play modules that ensure seamless interactions within our applications.   </p>
<p>Exception handling, an indispensable aspect of professional Java development, will also take center stage. By understanding how to predictably handle the unexpected, your programs become more robust and reliable. </p>
<p>Each topic in this chapter is a stepping stone towards advanced Java mastery, enhancing the structural integrity of your code.</p>
<h3 id="heading-interfaces-in-java">Interfaces in Java</h3>
<p>Interfaces in Java programming play an indispensable part in creating code modularity and promoting good software design practices. </p>
<p>An interface acts as a contract that specifies which methods a class must implement. It serves as an authoritative blueprint that ensures classes adhere to specific behaviors or functionalities.</p>
<p>Interfaces serve to establish loosely coupled relationships between classes. By employing interfaces, you can unbundle implementation details from class usage allowing greater flexibility and extensibility within your codebase.</p>
<p>One key concept associated with interfaces is their IS-A relationship. A class that implements an interface in Java is considered an implementation of that interface type. This means it inherits all its methods and must provide concrete implementations for them all.</p>
<p>So for instance, say we have an interface called <code>Shape</code>, with an implementation for its method called <code>calculateArea</code>. All classes implementing the <code>Shape</code> interface must provide their own implementation of <code>calculateArea</code>, so different shapes, such as circles or rectangles, have their own area calculation logic.</p>
<p>By taking advantage of IS-A relationships and interfaces, Java developers can achieve greater reusability, maintainability, and flexibility in their code. Interfaces serve as invaluable tools for maintaining uniform behavior between classes while encouraging modular and scalable application development.</p>
<p>Interfaces only declare methods – they don't provide implementation details. Instead, they serve as contracts that classes must abide by in order to conform to a standardized behavior or functionality. We will explore further the syntax, uses, and benefits of interfaces in Java programming in subsequent sections.</p>
<h4 id="heading-syntax-for-java-interfaces">Syntax for Java Interfaces</h4>
<p>Interfaces in Java provide a way for classes to form contracts that outline which methods and variables must be adhered to when implementing their interfaces. Their syntax follows an easily understandable structure.</p>
<p>To declare an interface in Java, you use the interface keyword followed by its name – for instance "foo".</p>
<p><strong>Example 1: Basic Interface Declaration</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Declare an interface named Printable</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Printable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span></span>; <span class="hljs-comment">// An abstract method with no implementation</span>
}
</code></pre>
<p><strong>Example 2: Interface with Constants</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Declare an interface named Constants</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Constants</span> </span>{
    <span class="hljs-comment">// Declare constant variables (implicitly public, static, and final)</span>
    <span class="hljs-keyword">int</span> MAX_VALUE = <span class="hljs-number">100</span>;
    String APP_NAME = <span class="hljs-string">"MyApp"</span>;
}
</code></pre>
<p><strong>Example 3: Interface Inheritance</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Declare an interface named Drawable</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Drawable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Another interface that extends Drawable</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Resizable</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Drawable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">resize</span><span class="hljs-params">()</span></span>;
}
</code></pre>
<p><strong>Example 4: Implementing an Interface in a Class</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Define an interface named Shape</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span></span>; <span class="hljs-comment">// Abstract method</span>
}

<span class="hljs-comment">// Create a class Circle that implements the Shape interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Drawing a Circle"</span>);
    }
}
</code></pre>
<p>In these examples:</p>
<ol>
<li>Example 1 demonstrates the basic syntax of declaring an interface with an abstract method.</li>
<li>Example 2 showcases an interface containing constant variables.</li>
<li>Example 3 illustrates interface inheritance, where one interface extends another.</li>
<li>Example 4 shows how to implement an interface in a class by providing concrete implementations for its abstract methods.</li>
</ol>
<p>Here are four more examples of Java code showcasing the syntax of interfaces in object-oriented programming:</p>
<p><strong>Example 5: Multiple Interface Implementation</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Declare two interfaces</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Printable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Displayable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">display</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// A class that implements both Printable and Displayable interfaces</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Document</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Printable</span>, <span class="hljs-title">Displayable</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">print</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Printing document..."</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">display</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Displaying document..."</span>);
    }
}
</code></pre>
<p><strong>Example 6: Interface with Default Method</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Declare an interface with a default method</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Logger</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">log</span><span class="hljs-params">(String message)</span></span>;

    <span class="hljs-comment">// Default method with an implementation</span>
    <span class="hljs-function"><span class="hljs-keyword">default</span> <span class="hljs-keyword">void</span> <span class="hljs-title">logError</span><span class="hljs-params">(String error)</span> </span>{
        System.err.println(<span class="hljs-string">"Error: "</span> + error);
    }
}

<span class="hljs-comment">// A class that implements the Logger interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">FileLogger</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Logger</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">log</span><span class="hljs-params">(String message)</span> </span>{
        System.out.println(<span class="hljs-string">"Logging: "</span> + message);
    }
}
</code></pre>
<p><strong>Example 7: Interface with Static Method</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Declare an interface with a static method</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">MathOperations</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span></span>;

    <span class="hljs-comment">// Static method</span>
    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">int</span> <span class="hljs-title">multiply</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>{
        <span class="hljs-keyword">return</span> a * b;
    }
}

<span class="hljs-comment">// A class that implements the MathOperations interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Calculator</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">MathOperations</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">int</span> <span class="hljs-title">add</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span> </span>{
        <span class="hljs-keyword">return</span> a + b;
    }
}
</code></pre>
<p><strong>Example 8: Functional Interface (Single Abstract Method)</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Declare a functional interface with a single abstract method</span>
<span class="hljs-meta">@FunctionalInterface</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Calculator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">int</span> <span class="hljs-title">calculate</span><span class="hljs-params">(<span class="hljs-keyword">int</span> a, <span class="hljs-keyword">int</span> b)</span></span>;
}

<span class="hljs-comment">// Using a lambda expression to implement the functional interface</span>
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Calculator addition = (a, b) -&gt; a + b;
        System.out.println(<span class="hljs-string">"Addition: "</span> + addition.calculate(<span class="hljs-number">5</span>, <span class="hljs-number">3</span>));
    }
}
</code></pre>
<p>In these additional examples:</p>
<ol>
<li>Example 5 demonstrates a class implementing multiple interfaces, <code>Printable</code> and <code>Displayable</code>.</li>
<li>Example 6 shows an interface with a default method, which provides a default implementation for one of its methods.</li>
<li>Example 7 includes an interface with a static method, which can be called without creating an instance of the interface.</li>
<li>Example 8 introduces a functional interface, which has a single abstract method. It also shows how to use a lambda expression to implement the functional interface.</li>
</ol>
<h3 id="heading-uses-of-interfaces-in-java">Uses of Interfaces in Java</h3>
<p>Interfaces play a crucial role in Java programming, offering numerous applications and benefits. Understanding how to utilize interfaces effectively can greatly enhance your code modularity and enable multiple inheritance. </p>
<p>Here are some key uses of interfaces in Java:</p>
<h4 id="heading-code-modularity">Code Modularity</h4>
<p>Interfaces provide many benefits to code modularity. By creating an interface contract between classes and methods implementation, ensuring consistent behavior and implementations that ease maintenance efforts as classes can be updated independently without disrupting overall program functionality.</p>
<p><strong>Basic Example: Code Modularity with Interfaces</strong></p>
<p>In this basic example, we'll create an interface called <code>Drawable</code> that defines a method <code>draw()</code>. Two different classes, <code>Circle</code> and <code>Rectangle</code>, will implement this interface to showcase code modularity.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Define an interface for Drawable objects</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Drawable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Class representing a Circle that implements the Drawable interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Drawable</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Drawing a Circle"</span>);
    }
}

<span class="hljs-comment">// Class representing a Rectangle that implements the Drawable interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Drawable</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Drawing a Rectangle"</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of Circle and Rectangle</span>
        Drawable circle = <span class="hljs-keyword">new</span> Circle();
        Drawable rectangle = <span class="hljs-keyword">new</span> Rectangle();

        <span class="hljs-comment">// Draw shapes without knowing their specific implementations</span>
        circle.draw();
        rectangle.draw();
    }
}
</code></pre>
<p><strong>Advanced Example: Code Modularity with Interfaces and Modifiable Shapes</strong></p>
<p>In this advanced example, we'll extend the concept of code modularity by introducing a modifiable shape interface (<code>ModifiableShape</code>). This interface will define methods for changing the size and color of shapes, allowing for more flexible modifications.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Define a basic interface for Drawable objects</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Drawable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Define an interface for Modifiable shapes with additional methods</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">ModifiableShape</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Drawable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setSize</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">setColor</span><span class="hljs-params">(String color)</span></span>;
}

<span class="hljs-comment">// Class representing a Circle that implements ModifiableShape</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ModifiableShape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;
    <span class="hljs-keyword">private</span> String color;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius, String color)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
        <span class="hljs-keyword">this</span>.color = color;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSize</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = Math.max(width, height) / <span class="hljs-number">2</span>;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setColor</span><span class="hljs-params">(String color)</span> </span>{
        <span class="hljs-keyword">this</span>.color = color;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Drawing a Circle with radius "</span> + radius + <span class="hljs-string">" and color "</span> + color);
    }
}

<span class="hljs-comment">// Class representing a Rectangle that implements ModifiableShape</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">ModifiableShape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> width;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;
    <span class="hljs-keyword">private</span> String color;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height, String color)</span> </span>{
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
        <span class="hljs-keyword">this</span>.color = color;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setSize</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">setColor</span><span class="hljs-params">(String color)</span> </span>{
        <span class="hljs-keyword">this</span>.color = color;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Drawing a Rectangle with dimensions "</span> + width + <span class="hljs-string">"x"</span> + height + <span class="hljs-string">" and color "</span> + color);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of Circle and Rectangle</span>
        ModifiableShape circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>, <span class="hljs-string">"Red"</span>);
        ModifiableShape rectangle = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">4.0</span>, <span class="hljs-number">6.0</span>, <span class="hljs-string">"Blue"</span>);

        <span class="hljs-comment">// Modify and draw shapes without knowing their specific implementations</span>
        circle.setSize(<span class="hljs-number">8.0</span>, <span class="hljs-number">8.0</span>);
        circle.setColor(<span class="hljs-string">"Green"</span>);
        circle.draw();

        rectangle.setSize(<span class="hljs-number">5.0</span>, <span class="hljs-number">7.0</span>);
        rectangle.setColor(<span class="hljs-string">"Yellow"</span>);
        rectangle.draw();
    }
}
</code></pre>
<h4 id="heading-enabling-multiple-inheritance">Enabling Multiple Inheritance</h4>
<p>While Java classes support only single inheritance, interfaces allow multiple inheritance. This enables developers to create classes which combine features from multiple interfaces into a flexible and robust code structure.</p>
<p><strong>Basic Example: Enabling Multiple Inheritance with Interfaces</strong></p>
<p>In this basic example, we'll create two interfaces, <code>Swimmable</code> and <code>Flyable</code>, and a class <code>Bird</code> that implements both interfaces to showcase multiple inheritance.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Define an interface for swimmable objects</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Swimmable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">swim</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Define an interface for flyable objects</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Flyable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">fly</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Class representing a Bird that implements both Swimmable and Flyable interfaces</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Bird</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Swimmable</span>, <span class="hljs-title">Flyable</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">swim</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Bird is swimming."</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">fly</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Bird is flying."</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Bird bird = <span class="hljs-keyword">new</span> Bird();

        <span class="hljs-comment">// Demonstrate multiple inheritance</span>
        bird.swim();
        bird.fly();
    }
}
</code></pre>
<p><strong>Advanced Example: Combining Multiple Interfaces for a Robot</strong></p>
<p>In this advanced example, we'll demonstrate the flexibility of combining multiple interfaces to create a <code>Robot</code> class with various capabilities, such as walking, flying, and swimming.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Define interfaces for different robot capabilities</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Walkable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">walk</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Flyable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">fly</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Swimmable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">swim</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Class representing a Robot that can combine multiple capabilities through interfaces</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Robot</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Walkable</span>, <span class="hljs-title">Flyable</span>, <span class="hljs-title">Swimmable</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">walk</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Robot is walking."</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">fly</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Robot is flying."</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">swim</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Robot is swimming."</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        Robot robot = <span class="hljs-keyword">new</span> Robot();

        <span class="hljs-comment">// Demonstrate the robot's capabilities</span>
        robot.walk();
        robot.fly();
        robot.swim();
    }
}
</code></pre>
<h4 id="heading-polymorphism-and-interface-implementation">Polymorphism and Interface Implementation</h4>
<p>Interfaces enable polymorphism in Java by permitting objects to be treated as instances of their implementing interfaces. This makes code reuse more likely and loose coupling between classes more adaptable and maintainable. </p>
<p>Interfaces provide the opportunity to define common functionality that multiple classes can implement to improve overall code structure.</p>
<h4 id="heading-basic-example-of-polymorphism-with-interfaces">Basic Example of Polymorphism with Interfaces</h4>
<p>This basic example explores polymorphism using interfaces by creating an interface called <code>Shape</code> with an associated <code>calculateArea()</code> method, then two classes named <code>Circle</code> and <code>Rectangle</code>. These classes implement this interface and represent instances of it as objects of their Shape interface. </p>
<p>We demonstrate polymorphism by treating objects as instances of their <code>Shape</code> interface.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Define an interface for shapes</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Class representing a Circle that implements the Shape interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }
}

<span class="hljs-comment">// Class representing a Rectangle that implements the Shape interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> width;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> width * height;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of Circle and Rectangle</span>
        Shape circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>);
        Shape rectangle = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">4.0</span>, <span class="hljs-number">6.0</span>);

        <span class="hljs-comment">// Calculate and print the areas without knowing the specific implementations</span>
        System.out.println(<span class="hljs-string">"Area of Circle: "</span> + circle.calculateArea());
        System.out.println(<span class="hljs-string">"Area of Rectangle: "</span> + rectangle.calculateArea());
    }
}
</code></pre>
<p><strong>Advanced Example: Dynamic Polymorphism with Interfaces</strong></p>
<p>In this advanced example, we'll introduce dynamic polymorphism by creating a <code>ShapeCalculator</code> class that operates on a list of <code>Shape</code> objects. This allows us to add more shapes without modifying the <code>ShapeCalculator</code> class, promoting code adaptability.</p>
<pre><code class="lang-java"><span class="hljs-keyword">import</span> java.util.ArrayList;
<span class="hljs-keyword">import</span> java.util.List;

<span class="hljs-comment">// Define an interface for shapes</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Class representing a Circle that implements the Shape interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }
}

<span class="hljs-comment">// Class representing a Rectangle that implements the Shape interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> width;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> width * height;
    }
}

<span class="hljs-comment">// Class to calculate the total area of a list of shapes</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ShapeCalculator</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateTotalArea</span><span class="hljs-params">(List&lt;Shape&gt; shapes)</span> </span>{
        <span class="hljs-keyword">double</span> totalArea = <span class="hljs-number">0.0</span>;
        <span class="hljs-keyword">for</span> (Shape shape : shapes) {
            totalArea += shape.calculateArea();
        }
        <span class="hljs-keyword">return</span> totalArea;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create a list of shapes</span>
        List&lt;Shape&gt; shapes = <span class="hljs-keyword">new</span> ArrayList&lt;&gt;();
        shapes.add(<span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>));
        shapes.add(<span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">4.0</span>, <span class="hljs-number">6.0</span>));

        <span class="hljs-comment">// Calculate and print the total area using dynamic polymorphism</span>
        <span class="hljs-keyword">double</span> totalArea = ShapeCalculator.calculateTotalArea(shapes);
        System.out.println(<span class="hljs-string">"Total Area of Shapes: "</span> + totalArea);
    }
}
</code></pre>
<h4 id="heading-api-design-and-abstraction">API Design and Abstraction</h4>
<p>Interfaces are frequently employed in API design to specify contracts for other developers to abide by when implementing an interface. This creates abstraction and provides a separation between contract fulfillment and its implementation. This also helps developers to focus on class behavior rather than specific implementation details.</p>
<p><strong>Basic Example: API Design with Interfaces</strong></p>
<p>In this basic example, we'll create an interface <code>DatabaseConnection</code> that defines methods for establishing a database connection. Other developers can implement this interface to provide specific database connection implementations.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Define an interface for establishing a database connection</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">DatabaseConnection</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">connect</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">disconnect</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// A class that implements the DatabaseConnection interface for MySQL</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MySQLConnection</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">DatabaseConnection</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">connect</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Connected to MySQL database"</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">disconnect</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Disconnected from MySQL database"</span>);
    }
}

<span class="hljs-comment">// A class that implements the DatabaseConnection interface for PostgreSQL</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">PostgreSQLConnection</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">DatabaseConnection</span> </span>{
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">connect</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Connected to PostgreSQL database"</span>);
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">disconnect</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Disconnected from PostgreSQL database"</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of database connections</span>
        DatabaseConnection mysqlConnection = <span class="hljs-keyword">new</span> MySQLConnection();
        DatabaseConnection postgresqlConnection = <span class="hljs-keyword">new</span> PostgreSQLConnection();

        <span class="hljs-comment">// Connect and disconnect from databases using the interface</span>
        mysqlConnection.connect();
        mysqlConnection.disconnect();

        postgresqlConnection.connect();
        postgresqlConnection.disconnect();
    }
}
</code></pre>
<p><strong>Advanced Example: Abstraction in API Design</strong></p>
<p>In this advanced example, we'll design an abstract API for managing various shapes using interfaces. We'll create an interface <code>Shape</code> that defines methods for calculating area and perimeter. Concrete classes like <code>Circle</code> and <code>Rectangle</code> will implement this interface to provide specific implementations.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Define an interface for shapes with methods for area and perimeter</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
    <span class="hljs-function"><span class="hljs-keyword">double</span> <span class="hljs-title">calculatePerimeter</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Class representing a Circle that implements the Shape interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculatePerimeter</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">2</span> * Math.PI * radius;
    }
}

<span class="hljs-comment">// Class representing a Rectangle that implements the Shape interface</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> width;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> width * height;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculatePerimeter</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> <span class="hljs-number">2</span> * (width + height);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Main</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of shapes</span>
        Shape circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>);
        Shape rectangle = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">4.0</span>, <span class="hljs-number">6.0</span>);

        <span class="hljs-comment">// Calculate and display area and perimeter using the interface</span>
        System.out.println(<span class="hljs-string">"Circle Area: "</span> + circle.calculateArea());
        System.out.println(<span class="hljs-string">"Circle Perimeter: "</span> + circle.calculatePerimeter());

        System.out.println(<span class="hljs-string">"Rectangle Area: "</span> + rectangle.calculateArea());
        System.out.println(<span class="hljs-string">"Rectangle Perimeter: "</span> + rectangle.calculatePerimeter());
    }
}
</code></pre>
<h3 id="heading-differences-between-classes-and-interfaces">Differences between Classes and Interfaces:</h3>
<p><strong>Inheritance</strong>: While classes may only extend one superclass, interfaces support multiple inheritance through the <code>extends</code> keyword. This enables interfaces to facilitate multiple inheritance in Java.</p>
<p><strong>Implementation</strong>: Classes can implement multiple interfaces by using the <code>implements</code> keyword. But only one superclass may extend a class.</p>
<p><strong>Instantiation:</strong> Objects may be instantiated directly from classes using the <code>new</code> keyword while interfaces cannot directly instantiated.</p>
<p><strong>Functionality:</strong> Classes may include both concrete methods with predefined implementations and abstract ones that require subclass implementation, while interfaces only declare methods without providing their implementations.</p>
<p><strong>Keyword:</strong> When it comes to class definition, we use the <code>class</code> keyword. When it comes to interface definition, however, <code>interface</code> should be used instead.</p>
<p><strong>Access Modifiers:</strong> Classes can have various access modifiers like public, protected, private and default while interfaces must always remain public with no further access modifiers available.</p>
<p><strong>Abstract Classes:</strong> Classes may be declared abstract, meaning they cannot be directly instantiated. Interfaces by definition are implicitly abstract.</p>
<p>Understanding the differences and similarities between classes and interfaces is vital for effective Java programming. </p>
<p>Classes provide implementation details and serve as building blocks of objects. Interfaces establish contracts for classes that implement them. </p>
<p>By taking full advantage of both types of objects, you can design robust yet flexible code structures.</p>
<h3 id="heading-multiple-inheritance-in-java-using-interface">Multiple Inheritance in Java Using Interface</h3>
<p>Java does not directly support multiple inheritance, where a class can inherit from multiple classes. But interfaces offer a way of accomplishing similar functionality through "interface inheritance."</p>
<p>Interface inheritance allows classes to implement multiple interfaces at the same time, inheriting all their methods and constants defined within those interfaces. By adopting multiple interfaces at once, a class may exhibit behaviors or characteristics from each of its inherited interfaces.</p>
<p>To illustrate how interfaces support multiple inheritance, let's use an example. Consider two interfaces: <code>Drawable</code> and <code>Movable</code>. Each defines their own method – one being <code>draw()</code> while <code>move()</code> is available from both.</p>
<p>An instance of the <code>Circle</code> class can implement both Drawable and Movable interfaces to grant itself the capability to both draw itself as well as move around freely. By doing so, this gives it the capability of drawing itself as well as moving its parts freely around.</p>
<pre><code class="lang-java">
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Drawable</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span></span>;

}

<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Movable</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">move</span><span class="hljs-params">()</span></span>;

}

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Drawable</span>, <span class="hljs-title">Movable</span> </span>{

    <span class="hljs-comment">// Implementing methods declared in the interfaces</span>

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{

        <span class="hljs-comment">// Code to draw a circle</span>

    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">move</span><span class="hljs-params">()</span> </span>{

        <span class="hljs-comment">// Code to move the circle</span>

    }

}
</code></pre>
<p>As shown above, the <code>Circle</code> class implements both <code>Drawable</code> and <code>Movable</code> interfaces, effectively inheriting their behaviors to operate as drawable and movable entities. This enables instances of this class to act both drawable and movable entities.</p>
<p>Interface inheritance differs from multiple inheritance in that it does not involve inheriting state or concrete implementation. Rather, its focus lies on inheriting method signatures and constants, providing benefits without some of the associated complexity.</p>
<p>Java programmers can take advantage of interface inheritance to develop flexible and modular code structures that support multiple behaviors or characteristics in their applications. This makes interfaces an excellent way of increasing code reuse and flexibility in Java programming.</p>
<h3 id="heading-abstract-classes-and-methods-in-java">Abstract Classes and Methods in Java</h3>
<p>Previously, we talked about abstraction in Objected Oriented Programming. Here are some examples of abstractions using abstract classes and methods.</p>
<h4 id="heading-abstract-classes">Abstract Classes</h4>
<p>An abstract class serves as a blueprint for other classes and cannot be instantiated itself. It acts as a partial implementation, providing a common interface and defining certain methods that derived classes must implement. </p>
<p>By marking a class as abstract, you can create a clear separation between the implementation details and the higher-level functionality. </p>
<p>Here are several examples to showcase the proper way of using abstract classes.</p>
<p><strong>Example 1: Initializing an Abstract Class (Error)</strong></p>
<p>In this example, we have defined an abstract class <code>Person</code> with an abstract method <code>introduceYourself()</code>. </p>
<p>Abstract classes cannot be instantiated directly, which means you cannot create an object of an abstract class using the <code>new</code> keyword. Attempting to do so will result in a compilation error because abstract classes are meant to be extended by concrete (non-abstract) subclasses that provide implementations for their abstract methods.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract class representing a Person</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span> </span>{
    <span class="hljs-keyword">private</span> String name;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Person</span><span class="hljs-params">(String name)</span> </span>{
        <span class="hljs-keyword">this</span>.name = name;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">void</span> <span class="hljs-title">introduceYourself</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InitializationErrorExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Attempt to initialize an abstract class (Person)</span>
        Person person = <span class="hljs-keyword">new</span> Person(<span class="hljs-string">"John"</span>); <span class="hljs-comment">// Error: Cannot instantiate the abstract class Person</span>
    }
}
</code></pre>
<p>Here's the output:</p>
<pre><code class="lang-java">Error: Cannot instantiate the <span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Person</span></span>
</code></pre>
<p><strong>Example 2: Simple Abstract Class and Regular Class</strong></p>
<p>In this example, we have an abstract class <code>Shape</code> with an abstract method <code>calculateArea()</code>. We also have a concrete class <code>Circle</code> that extends the <code>Shape</code> class and provides an implementation for the <code>calculateArea()</code> method. In the <code>main()</code> method, we create an instance of <code>Circle</code> and calculate the area of the circle.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract class representing a Shape</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Concrete class Circle extending Shape</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">SimpleAbstractClassExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create an instance of Circle</span>
        Circle circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>);

        <span class="hljs-comment">// Calculate and print the area of the circle</span>
        System.out.println(<span class="hljs-string">"Area of Circle: "</span> + circle.calculateArea());
    }
}
</code></pre>
<p>Here's the output:</p>
<pre><code class="lang-java">Area of Circle: <span class="hljs-number">78.53981633974483</span>
</code></pre>
<p><strong>Example 3: Abstract Class with Abstract and Regular Methods</strong></p>
<p>In this example, we have an abstract class <code>Vehicle</code> with both abstract and regular methods. The <code>start()</code> method has a default implementation, while the <code>stop()</code> method is abstract and must be overridden by concrete subclasses. </p>
<p>We have a concrete class <code>Car</code> that extends <code>Vehicle</code> and provides an implementation for the <code>stop()</code> method. In the <code>main()</code> method, we create an instance of <code>Car</code>, demonstrating the difference between abstract and regular methods.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract class representing a Shape</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printDescription</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"This is a shape."</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Concrete class Circle extending Shape</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printDescription</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"This is a circle."</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OverrideRegularMethodExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create an instance of Circle</span>
        Circle circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>);

        <span class="hljs-comment">// Print the description and calculate the area of the circle</span>
        circle.printDescription();
        System.out.println(<span class="hljs-string">"Area of Circle: "</span> + circle.calculateArea());
    }
}
</code></pre>
<p>Here's the output:</p>
<pre><code class="lang-java">Vehicle started.
Car stopped.
</code></pre>
<p><strong>Example 4: Overriding a Regular Method of an Abstract Class</strong></p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract class representing a Shape</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printDescription</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"This is a shape."</span>);
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Concrete class Circle extending Shape</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }

    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printDescription</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"This is a circle."</span>);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">OverrideRegularMethodExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create an instance of Circle</span>
        Circle circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>);

        <span class="hljs-comment">// Print the description and calculate the area of the circle</span>
        circle.printDescription();
        System.out.println(<span class="hljs-string">"Area of Circle: "</span> + circle.calculateArea());
    }
}
</code></pre>
<p>Here's the output:</p>
<pre><code class="lang-java">This is a circle.
Area of Circle: <span class="hljs-number">78.53981633974483</span>
</code></pre>
<p><strong>Example 5: Implementing Drawable Interface with Shape Abstract Class in Java</strong></p>
<p>In the Java code below, we have an interface named <code>Drawable</code> is defined with a single method <code>draw()</code>. An abstract class <code>Shape</code> is created that implements the <code>Drawable</code> interface. This class has: </p>
<ul>
<li>an instance variable <code>color</code>, and an abstract method <code>calculateArea()</code> to calculate the area of the shape</li>
<li>a concrete method <code>printColor()</code> to print the color of the shape</li>
<li>an implementation of the <code>draw()</code> method from the <code>Drawable</code> interface</li>
</ul>
<p>Two concrete classes, <code>Circle</code> and <code>Rectangle</code>, extend the <code>Shape</code> class. They provide specific implementations for the <code>calculateArea()</code> method based on their respective geometries. </p>
<p>The <code>main()</code> method demonstrates the use of these classes and interfaces: Instances of <code>Circle</code> and <code>Rectangle</code> are created with specified colors and dimensions. </p>
<p>The <code>printColor()</code>, <code>calculateArea()</code>, and <code>draw()</code> methods are called on these instances to showcase the functionality and the implementation of the interface.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Interface for Drawable objects</span>
<span class="hljs-class"><span class="hljs-keyword">interface</span> <span class="hljs-title">Drawable</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Abstract class representing a Shape</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> <span class="hljs-keyword">implements</span> <span class="hljs-title">Drawable</span> </span>{
    <span class="hljs-keyword">private</span> String color;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Shape</span><span class="hljs-params">(String color)</span> </span>{
        <span class="hljs-keyword">this</span>.color = color;
    }

    <span class="hljs-comment">// Abstract method to calculate area</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;

    <span class="hljs-comment">// Concrete method to print the color</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">printColor</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Color: "</span> + color);
    }

    <span class="hljs-comment">// Implementing the draw method from the Drawable interface</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">draw</span><span class="hljs-params">()</span> </span>{
        System.out.println(<span class="hljs-string">"Drawing a shape with color "</span> + color);
    }
}

<span class="hljs-comment">// Concrete class Circle extending Shape</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(String color, <span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">super</span>(color);
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-comment">// Override to provide the area calculation for a circle</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }
}

<span class="hljs-comment">// Concrete class Rectangle extending Shape</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> width;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span><span class="hljs-params">(String color, <span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">super</span>(color);
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-comment">// Override to provide the area calculation for a rectangle</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> width * height;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AdvancedAbstractClassExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of Circle and Rectangle</span>
        Circle circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-string">"Red"</span>, <span class="hljs-number">5.0</span>);
        Rectangle rectangle = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-string">"Blue"</span>, <span class="hljs-number">4.0</span>, <span class="hljs-number">6.0</span>);

        <span class="hljs-comment">// Call methods and demonstrate the use of interfaces</span>
        circle.printColor();
        System.out.println(<span class="hljs-string">"Area of Circle: "</span> + circle.calculateArea());
        circle.draw();

        System.out.println();

        rectangle.printColor();
        System.out.println(<span class="hljs-string">"Area of Rectangle: "</span> + rectangle.calculateArea());
        rectangle.draw();
    }
}
</code></pre>
<p>Here's the output:</p>
<pre><code class="lang-java">Color: Red
Area of Circle: <span class="hljs-number">78.53981633974483</span>
Drawing a shape with color Red

Color: Blue
Area of Rectangle: <span class="hljs-number">24.0</span>
Drawing a shape with color Blue
</code></pre>
<h4 id="heading-abstract-methods">Abstract Methods</h4>
<p>Abstract methods, unlike regular methods, do not have an implementation. They are declared using the <code>abstract</code> keyword and must be overridden by any concrete class that extends the abstract class. These methods provide a way for developers to enforce specific behavior in derived classes.</p>
<p>In the code below, we have an abstract class <code>Shape</code> that contains an abstract method <code>calculateArea()</code>. Abstract methods are declared using the <code>abstract</code> keyword and do not have an implementation.</p>
<p>We also have concrete subclasses <code>Circle</code> and <code>Rectangle</code> that extend the <code>Shape</code> class and provide their implementations of the <code>calculateArea()</code> method. These subclasses are required to override the abstract method.</p>
<p>And in the <code>main()</code> method, we create instances of <code>Circle</code> and <code>Rectangle</code> and calculate their respective areas using the overridden <code>calculateArea()</code> methods.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Abstract class with an abstract method</span>
<span class="hljs-keyword">abstract</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-comment">// Abstract method declaration</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">abstract</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span></span>;
}

<span class="hljs-comment">// Concrete subclass Circle extending Shape</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Circle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> radius;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Circle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> radius)</span> </span>{
        <span class="hljs-keyword">this</span>.radius = radius;
    }

    <span class="hljs-comment">// Implementing the abstract method</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> Math.PI * radius * radius;
    }
}

<span class="hljs-comment">// Concrete subclass Rectangle extending Shape</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Rectangle</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Shape</span> </span>{
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> width;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> height;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">Rectangle</span><span class="hljs-params">(<span class="hljs-keyword">double</span> width, <span class="hljs-keyword">double</span> height)</span> </span>{
        <span class="hljs-keyword">this</span>.width = width;
        <span class="hljs-keyword">this</span>.height = height;
    }

    <span class="hljs-comment">// Implementing the abstract method</span>
    <span class="hljs-meta">@Override</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">calculateArea</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> width * height;
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AbstractMethodExample</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-comment">// Create instances of Circle and Rectangle</span>
        Circle circle = <span class="hljs-keyword">new</span> Circle(<span class="hljs-number">5.0</span>);
        Rectangle rectangle = <span class="hljs-keyword">new</span> Rectangle(<span class="hljs-number">4.0</span>, <span class="hljs-number">6.0</span>);

        <span class="hljs-comment">// Calculate and print the areas</span>
        System.out.println(<span class="hljs-string">"Area of Circle: "</span> + circle.calculateArea());
        System.out.println(<span class="hljs-string">"Area of Rectangle: "</span> + rectangle.calculateArea());
    }
}
</code></pre>
<p>Abstract classes and methods in Java offer a powerful mechanism for defining common behavior and ensuring proper implementation in object-oriented programming. They promote code reusability, maintainability, and provide clear separation between higher-level functionality and implementation details. </p>
<p>By utilizing abstract classes and methods effectively, you can write cleaner and more modular code in your Java applications.</p>
<h3 id="heading-exception-handling-in-java">Exception Handling in Java</h3>
<p>In the world of programming, it's essential to grasp the inevitability of mistakes. Errors occur, but what truly differentiates a seasoned programmer from the rest is how these errors are handled. </p>
<p>Within Java, 'exceptions' serve as our key indicators of anomalies during the execution of our programs. Recognizing and managing these exceptions judiciously ensures that our applications remain robust and fault-tolerant. </p>
<p>Fortunately, Java equips you with a rich mechanism to adeptly handle these exceptions, paving the way for resilient software design.</p>
<h4 id="heading-fundamentals-of-exceptions">Fundamentals of Exceptions</h4>
<p>In Java, exceptions are unexpected conditions during program execution, arising from issues like invalid input or unavailable resources. Errors are more severe, systemic issues. </p>
<p>Exceptions, manageable and often anticipated, are classified into Checked Exceptions, which must be caught by the compiler, and Unchecked Exceptions, usually due to logical flaws and runtime scenarios.</p>
<pre><code class="lang-java"><span class="hljs-comment">// Importing necessary classes for demonstration</span>
<span class="hljs-keyword">import</span> java.io.File;
<span class="hljs-keyword">import</span> java.io.FileNotFoundException;
<span class="hljs-keyword">import</span> java.util.Scanner;

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExceptionExample</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{

        <span class="hljs-comment">// Demonstrating Checked Exception</span>
        <span class="hljs-comment">// Checked Exceptions are anticipated by the compiler and we are required to handle them</span>
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Attempting to read a file that may not exist</span>
            Scanner fileScanner = <span class="hljs-keyword">new</span> Scanner(<span class="hljs-keyword">new</span> File(<span class="hljs-string">"somefile.txt"</span>));
        } <span class="hljs-keyword">catch</span> (FileNotFoundException e) {
            <span class="hljs-comment">// FileNotFoundException is a checked exception</span>
            System.out.println(<span class="hljs-string">"Checked Exception: File not found."</span>);
        }

        <span class="hljs-comment">// Demonstrating Unchecked Exception</span>
        <span class="hljs-comment">// Unchecked Exceptions usually result from logical flaws and manifest during runtime</span>
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Dividing by zero - a logical flaw</span>
            <span class="hljs-keyword">int</span> result = <span class="hljs-number">10</span> / <span class="hljs-number">0</span>;
        } <span class="hljs-keyword">catch</span> (ArithmeticException e) {
            <span class="hljs-comment">// ArithmeticException is an unchecked exception</span>
            System.out.println(<span class="hljs-string">"Unchecked Exception: Cannot divide by zero."</span>);
        }

        <span class="hljs-comment">// Note: Errors are different from Exceptions and usually indicate severe problems</span>
        <span class="hljs-comment">// that a reasonable application should not try to catch.</span>
        <span class="hljs-comment">// For instance, OutOfMemoryError, StackOverflowError, etc.</span>
    }
}
</code></pre>
<p>In this code:</p>
<ul>
<li>We attempt to open a file named <code>somefile.txt</code>. If this file doesn't exist, a <code>FileNotFoundException</code> is thrown. This is a checked exception, which means the compiler ensures that we handle this potential error condition.</li>
<li>We also include a simple division operation that results in a division by zero. This leads to an <code>ArithmeticException</code>, an unchecked exception, highlighting logical flaws that only appear during runtime.</li>
<li>Errors such as <code>OutOfMemoryError</code> are beyond the scope of this example, but it's crucial to understand that they denote more serious system-level problems and are typically not caught in standard applications.</li>
</ul>
<h4 id="heading-basic-exception-handling-try-catch">Basic Exception Handling: try-catch</h4>
<p>Java's <code>try-catch</code> is used to handle potential exceptions, ensuring the program runs continuously. Multiple <code>catch</code> blocks can manage various exceptions. The <code>finally</code> block performs cleanup, executing regardless of whether an exception occurs, to properly release or close resources.</p>
<p>Below is a code example that showcases the use of Java's <code>try-catch</code> mechanism, along with multiple <code>catch</code> blocks and a <code>finally</code> block:</p>
<pre><code class="lang-java">
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">TryCatchExample</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{

        <span class="hljs-comment">// Resource we want to manage, for the sake of this example let's use a String</span>
        String resource = <span class="hljs-string">"exampleResource"</span>;

        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Code that might throw exceptions</span>
            System.out.println(<span class="hljs-string">"Resource in use: "</span> + resource);

            <span class="hljs-comment">// This will trigger an ArithmeticException</span>
            <span class="hljs-keyword">int</span> result = <span class="hljs-number">10</span> / <span class="hljs-number">0</span>;

            <span class="hljs-comment">// This line will not be executed due to the exception above</span>
            System.out.println(result);

        } <span class="hljs-keyword">catch</span> (ArithmeticException e) {
            <span class="hljs-comment">// Handle arithmetic exception</span>
            System.out.println(<span class="hljs-string">"Caught ArithmeticException: "</span> + e.getMessage());

        } <span class="hljs-keyword">catch</span> (Exception e) {
            <span class="hljs-comment">// General exception handler</span>
            System.out.println(<span class="hljs-string">"Caught General Exception: "</span> + e.getMessage());

        } <span class="hljs-keyword">finally</span> {
            <span class="hljs-comment">// Clean-up operations</span>
            resource = <span class="hljs-keyword">null</span>;
            System.out.println(<span class="hljs-string">"Resource has been released."</span>);
        }
    }
}
</code></pre>
<p>Here's the output:</p>
<pre><code class="lang-java">Resource in use: exampleResource
Caught ArithmeticException: / by zero
Resource has been released.
</code></pre>
<p>What's going on in the code above:</p>
<ol>
<li>We start by "using" a resource. In real scenarios, this could be a file handle, a database connection, or other resources.</li>
<li>Inside the <code>try</code> block, an intentional division by zero is performed to trigger an <code>ArithmeticException</code>.</li>
<li>The <code>catch</code> block for <code>ArithmeticException</code> handles this specific type of exception.</li>
<li>A general <code>Exception</code> catch block is also present to handle any other types of exceptions.</li>
<li>The <code>finally</code> block ensures that, regardless of whether an exception was thrown or not, the resource is "released". In this example, releasing just means setting the <code>resource</code> to <code>null</code>. In real-life scenarios, this might involve closing a file or disconnecting from a network.</li>
</ol>
<h4 id="heading-advanced-exception-handling-mechanisms">Advanced Exception Handling Mechanisms</h4>
<p>Java offers advanced tools beyond the basic structure. The <code>try-with-resources</code> automatically handles resource closure. Exception chaining allows tracing back to the root cause. It also supports refined exception control through rethrowing and enhanced type-checking.</p>
<p><strong>Try-with-resources</strong>: Java introduced the <code>try-with-resources</code> statement in Java 7 as part of the <code>java.lang.AutoCloseable</code> interface. Resources that implement this interface (like streams) can be auto-closed once they're no longer in use.</p>
<p><strong>Exception Chaining</strong>: This allows exceptions to be linked. When a new exception is thrown because another exception occurs, it's helpful to maintain the original exception as the cause.</p>
<pre><code class="lang-java">
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">ExceptionChainingExample</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            someMethod();
        } <span class="hljs-keyword">catch</span> (Exception e) {
            System.out.println(e.getMessage());
            System.out.println(<span class="hljs-string">"Caused by: "</span> + e.getCause().getMessage());
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">someMethod</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> Exception </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Some code that throws an exception</span>
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> RuntimeException(<span class="hljs-string">"Initial exception"</span>);
        } <span class="hljs-keyword">catch</span> (RuntimeException e) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> Exception(<span class="hljs-string">"New exception"</span>, e);  <span class="hljs-comment">// Chain the caught exception</span>
        }
    }
}
</code></pre>
<p><strong>Rethrowing with Enhanced Type-Checking</strong>: Java 7 introduced the ability to rethrow exceptions with improved type checking, ensuring safer exception handling.</p>
<pre><code class="lang-java">
<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">RethrowingExample</span> </span>{

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        <span class="hljs-keyword">try</span> {
            testRethrow();
        } <span class="hljs-keyword">catch</span> (IOException | RuntimeException e) {
            System.out.println(e.getMessage());
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">testRethrow</span><span class="hljs-params">()</span> <span class="hljs-keyword">throws</span> IOException, RuntimeException </span>{
        <span class="hljs-keyword">try</span> {
            <span class="hljs-comment">// Some code that throws an exception</span>
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> IOException(<span class="hljs-string">"IO exception"</span>);
        } <span class="hljs-keyword">catch</span> (Exception e) {
            <span class="hljs-comment">// Re-throwing the exception with enhanced type-checking</span>
            <span class="hljs-keyword">throw</span> e;
        }
    }
}
</code></pre>
<p><strong>Note</strong>: In the last example, even though the catch block captures a general <code>Exception</code>, the <code>testRethrow</code> method's signature indicates that it can only throw <code>IOException</code> and <code>RuntimeException</code>. Java's enhanced type-checking ensures that this is the case, and the code will not compile if <code>throw e</code> could result in an exception type other than those two.</p>
<p><strong>Using <code>throw</code> and <code>throws</code></strong>: While Java provides an extensive range of exceptions, there will be instances demanding custom exceptions to better represent specific error conditions. </p>
<p>The <code>throw</code> keyword facilitates this, letting you craft and launch a custom exception. Conversely, <code>throws</code> operates at the method signature level, indicating that a particular method may cause specific exceptions, compelling callers to address them.</p>
<h4 id="heading-creating-custom-exceptions">Creating Custom Exceptions</h4>
<p>Custom exceptions, though conceptually similar to Java's built-in ones, offer a more detailed portrayal of issues. By simply extending the <code>Exception</code> class, you can create bespoke exceptions tailored to your application's needs. Such specificity not only enhances error representation but also aids in more informed error handling and resolution.</p>
<p>Here's the modified version of the previous example:</p>
<pre><code class="lang-java">
<span class="hljs-comment">// Custom exception class</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InvalidWithdrawalAmountException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exception</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">InvalidWithdrawalAmountException</span><span class="hljs-params">(String message)</span> </span>{
        <span class="hljs-keyword">super</span>(message);  <span class="hljs-comment">// Passing the error message to the base Exception class</span>
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BankAccount</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> balance;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">BankAccount</span><span class="hljs-params">(<span class="hljs-keyword">double</span> balance)</span> </span>{
        <span class="hljs-keyword">this</span>.balance = balance;
    }

    <span class="hljs-comment">// Method to withdraw money from the account</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">withdraw</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> <span class="hljs-keyword">throws</span> InvalidWithdrawalAmountException </span>{
        <span class="hljs-keyword">if</span> (amount &lt; <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidWithdrawalAmountException(<span class="hljs-string">"Withdrawal amount cannot be negative."</span>);
        } <span class="hljs-keyword">else</span> <span class="hljs-keyword">if</span> (amount &gt; balance) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidWithdrawalAmountException(<span class="hljs-string">"Withdrawal amount exceeds account balance."</span>);
        } <span class="hljs-keyword">else</span> {
            balance -= amount;
            System.out.println(<span class="hljs-string">"Withdrawal successful. New balance: "</span> + balance);
        }
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        BankAccount account = <span class="hljs-keyword">new</span> BankAccount(<span class="hljs-number">500</span>);

        <span class="hljs-keyword">try</span> {
            account.withdraw(<span class="hljs-number">600</span>);  <span class="hljs-comment">// This should trigger our custom exception</span>
        } <span class="hljs-keyword">catch</span> (InvalidWithdrawalAmountException e) {
            System.out.println(<span class="hljs-string">"Error: "</span> + e.getMessage());  <span class="hljs-comment">// Handle the custom exception by printing out the error message</span>
        } <span class="hljs-keyword">catch</span> (Exception e) {  <span class="hljs-comment">// This catch block will handle general exceptions</span>
            System.out.println(<span class="hljs-string">"A general error occurred: "</span> + e.getMessage());
        }
    }
}
</code></pre>
<h4 id="heading-best-practices-in-exception-handling">Best Practices in Exception Handling</h4>
<p>Exception handling, when done right, can be an asset. Don't use empty <code>catch</code> blocks, which merely swallow exceptions, leaving them unaddressed. Instead, focus on catching the most specific exceptions before any generic ones. Steer clear of deploying exceptions as regular control flow tools. And remember, always document exceptions using JavaDoc, guiding other developers in anticipating and managing potential pitfalls.</p>
<p>Here's a <code>BankAccount</code> class example which showcases multiple custom exceptions:</p>
<pre><code class="lang-java">
<span class="hljs-comment">/**
 * Custom exception for insufficient funds.
 */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InsufficientFundsException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exception</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">InsufficientFundsException</span><span class="hljs-params">(String message)</span> </span>{
        <span class="hljs-keyword">super</span>(message);
    }
}

<span class="hljs-comment">/**
 * Custom exception for invalid deposit amounts.
 */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InvalidDepositAmountException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exception</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">InvalidDepositAmountException</span><span class="hljs-params">(String message)</span> </span>{
        <span class="hljs-keyword">super</span>(message);
    }
}

<span class="hljs-comment">/**
 * Custom exception for invalid withdrawal amounts.
 */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">InvalidWithdrawalAmountException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exception</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">InvalidWithdrawalAmountException</span><span class="hljs-params">(String message)</span> </span>{
        <span class="hljs-keyword">super</span>(message);
    }
}

<span class="hljs-comment">/**
 * Custom exception for a frozen account.
 */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">AccountFrozenException</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">Exception</span> </span>{
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">AccountFrozenException</span><span class="hljs-params">(String message)</span> </span>{
        <span class="hljs-keyword">super</span>(message);
    }
}

<span class="hljs-keyword">public</span> <span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">BankAccount</span> </span>{

    <span class="hljs-keyword">private</span> <span class="hljs-keyword">double</span> balance;
    <span class="hljs-keyword">private</span> <span class="hljs-keyword">boolean</span> isFrozen;

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-title">BankAccount</span><span class="hljs-params">(<span class="hljs-keyword">double</span> initialBalance)</span> </span>{
        <span class="hljs-keyword">this</span>.balance = initialBalance;
        <span class="hljs-keyword">this</span>.isFrozen = <span class="hljs-keyword">false</span>;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">freezeAccount</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">this</span>.isFrozen = <span class="hljs-keyword">true</span>;
    }

    <span class="hljs-comment">/**
     * Deposit money into the bank account.
     *
     * <span class="hljs-doctag">@param</span> amount Amount to deposit.
     * <span class="hljs-doctag">@throws</span> InvalidDepositAmountException if the deposit amount is non-positive.
     * <span class="hljs-doctag">@throws</span> AccountFrozenException if the account is frozen.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">deposit</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> <span class="hljs-keyword">throws</span> InvalidDepositAmountException, AccountFrozenException </span>{
        <span class="hljs-keyword">if</span> (isFrozen) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> AccountFrozenException(<span class="hljs-string">"Account is frozen, cannot perform operations."</span>);
        }
        <span class="hljs-keyword">if</span> (amount &lt;= <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidDepositAmountException(<span class="hljs-string">"Deposit amount must be positive."</span>);
        }
        balance += amount;
    }

    <span class="hljs-comment">/**
     * Withdraw money from the bank account.
     *
     * <span class="hljs-doctag">@param</span> amount Amount to withdraw.
     * <span class="hljs-doctag">@throws</span> InsufficientFundsException if there isn't enough balance.
     * <span class="hljs-doctag">@throws</span> InvalidWithdrawalAmountException if the withdrawal amount is non-positive.
     * <span class="hljs-doctag">@throws</span> AccountFrozenException if the account is frozen.
     */</span>
    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">void</span> <span class="hljs-title">withdraw</span><span class="hljs-params">(<span class="hljs-keyword">double</span> amount)</span> <span class="hljs-keyword">throws</span> InsufficientFundsException, InvalidWithdrawalAmountException, AccountFrozenException </span>{
        <span class="hljs-keyword">if</span> (isFrozen) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> AccountFrozenException(<span class="hljs-string">"Account is frozen, cannot perform operations."</span>);
        }
        <span class="hljs-keyword">if</span> (amount &lt;= <span class="hljs-number">0</span>) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InvalidWithdrawalAmountException(<span class="hljs-string">"Withdrawal amount must be positive."</span>);
        }
        <span class="hljs-keyword">if</span> (balance &lt; amount) {
            <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> InsufficientFundsException(<span class="hljs-string">"Insufficient funds in the account."</span>);
        }
        balance -= amount;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">double</span> <span class="hljs-title">getBalance</span><span class="hljs-params">()</span> </span>{
        <span class="hljs-keyword">return</span> balance;
    }

    <span class="hljs-function"><span class="hljs-keyword">public</span> <span class="hljs-keyword">static</span> <span class="hljs-keyword">void</span> <span class="hljs-title">main</span><span class="hljs-params">(String[] args)</span> </span>{
        BankAccount account = <span class="hljs-keyword">new</span> BankAccount(<span class="hljs-number">500.0</span>);

        <span class="hljs-keyword">try</span> {
            account.deposit(-<span class="hljs-number">50</span>);
        } <span class="hljs-keyword">catch</span> (Exception e) {
            System.out.println(<span class="hljs-string">"Error: "</span> + e.getMessage());
        }

        <span class="hljs-keyword">try</span> {
            account.withdraw(<span class="hljs-number">600</span>);
        } <span class="hljs-keyword">catch</span> (Exception e) {
            System.out.println(<span class="hljs-string">"Error: "</span> + e.getMessage());
        }

        <span class="hljs-keyword">try</span> {
            account.freezeAccount();
            account.deposit(<span class="hljs-number">50</span>);
        } <span class="hljs-keyword">catch</span> (Exception e) {
            System.out.println(<span class="hljs-string">"Error: "</span> + e.getMessage());
        }

        System.out.println(<span class="hljs-string">"Current balance: "</span> + account.getBalance());
    }
}
</code></pre>
<p>This <code>BankAccount</code> class has:</p>
<ol>
<li>Four custom exceptions: <code>InsufficientFundsException</code>, <code>InvalidDepositAmountException</code>, <code>InvalidWithdrawalAmountException</code>, and <code>AccountFrozenException</code>.</li>
<li>Methods for depositing, withdrawing, and checking the balance. Each method can throw multiple exceptions based on various conditions.</li>
<li>In the <code>main</code> method, three different scenarios are executed to demonstrate the triggering of these exceptions.</li>
</ol>
<h4 id="heading-common-mistakes-and-how-to-avoid-them">Common Mistakes and How to Avoid Them</h4>
<p>A few common pitfalls deserve mention. Catching the generic <code>Exception</code> or <code>Throwable</code> without justification can mask issues. Letting exceptions go unheeded or ‘swallowing’ them can leave underlying problems unresolved. </p>
<p>Moreover, introducing exceptions within <code>finally</code> blocks can overshadow primary exceptions, leading to obscured debugging.</p>
<p><strong>Catching the generic Exception or Throwable without justification:</strong></p>
<pre><code class="lang-java">
<span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// some code that might throw exceptions</span>
} <span class="hljs-keyword">catch</span> (Exception e) {
    <span class="hljs-comment">// This catch block is too generic, and can mask specific issues</span>
    e.printStackTrace();
}
</code></pre>
<p><strong>Letting exceptions go unheeded or ‘swallowing’ them:</strong></p>
<pre><code class="lang-java">
<span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// some code that might throw exceptions</span>
} <span class="hljs-keyword">catch</span> (SpecificException e) {
    <span class="hljs-comment">// This catch block is empty, 'swallowing' the exception</span>
    <span class="hljs-comment">// No action is taken to address the underlying problem</span>
}
</code></pre>
<p><strong>Introducing exceptions within finally blocks:</strong></p>
<pre><code class="lang-java">
<span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// some code that might throw exceptions</span>
} <span class="hljs-keyword">catch</span> (SpecificException e) {
    <span class="hljs-comment">// Handle specific exception</span>
    e.printStackTrace();
} <span class="hljs-keyword">finally</span> {
    <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// some cleanup code that might throw exceptions</span>
    } <span class="hljs-keyword">catch</span> (AnotherException e) {
        <span class="hljs-comment">// Introducing exceptions in the finally block</span>
        <span class="hljs-comment">// This can overshadow primary exceptions, making debugging difficult</span>
        e.printStackTrace();
    }
}
</code></pre>
<h4 id="heading-practical-scenarios-and-use-cases-2">Practical Scenarios and Use-cases</h4>
<p>Exception handling proves its worth in many scenarios:</p>
<ul>
<li>Validating input in user-centric forms, ensuring data integrity.</li>
<li>Engaging in file operations, be it reading or writing, guaranteeing data security and accuracy.</li>
<li>Managing database connections, especially when handling SQL exceptions, preserving database integrity.</li>
</ul>
<p>Exception handling isn't just a technical facet of Java – it's an art that bolsters the resilience of your applications. </p>
<p>As you embark on your Java journey, let the conscientious management of exceptions be a constant companion. Remember, it's not the absence of exceptions but the mastery over them that delineates proficient coding. Marry this with Java’s other exquisite features, and you’re on the path to crafting truly holistic and robust software.</p>
<h2 id="heading-closing">Closing</h2>
<p>As we draw the curtains on this comprehensive journey through the fundamentals of Java and Object-Oriented Programming, I hope you have a sense of accomplishment and great anticipation for the code you'll craft. </p>
<p>From the first stirrings of curiosity in "Why Java?" to the solid foundation laid in the basics of Java programs, we've traversed the expansive terrain of data types, wrestled with the logical interplay of operators, and embraced the structured flow of control statements.</p>
<p>The adventure intensified as we ventured into the heart of Java — Object-Oriented Programming (OOP). We learned how classes, objects, constructors, and the principles of inheritance, polymorphism, encapsulation, and abstraction are not just terms but can be the tools in your programming arsenal.</p>
<p>Finally, Chapter 5 crowned our efforts, unlocking the sophisticated chambers of advanced Java with Interfaces, abstract classes and methods, and the art of exception handling. With this knowledge, you can ensure that your programs not only run but also adapt and thrive in the unpredictable landscape of real-world applications.</p>
<p>The essence of Java, with its OOP principles, now lies at your fingertips, ready to be applied, explored, and expanded. Whether you're crafting simple programs or architecting complex systems, the concepts encapsulated within these pages will serve as a continuous reference and guide.</p>
<p>Your journey through the pages of this handbook has prepared you not only for the technicalities of Java but for the innovative application of its principles across various domains. Each chapter has been a stepping stone to understanding the power and elegance of Java programming, culminating in the advanced concepts that will now serve as a springboard for your future endeavors.</p>
<p>Let each line of code you write reflect the insights gained, and may your path in Java programming be as rewarding as the process of bringing this handbook to life. Happy coding!</p>
<h2 id="heading-how-to-become-data-and-ai-specialist">How to Become Data and AI Specialist</h2>
<p>You can launch your data science career with my company's <a target="_blank" href="https://lunartech.ai/course-overview/">Ultimate Data Science Bootcamp</a>. Dive into hands-on learning and Python skills that will lift you to industry leader status. Sign up, take charge of your future, and start making waves in tech today.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://lunartech.ai/">https://lunartech.ai/</a></div>
<p>Elevate your Java expertise with our comprehensive eBook at no cost. It's a hands-on guide brimming with practical advice to refine your coding technique, ace technical interviews, and construct an impressive Java-focused resume. Immerse yourself in advanced concepts through real-world scenarios, and gain access to networking strategies that will broaden your professional horizons. Don’t just code—build a career. Download your copy today and start making meaningful strides in the tech industry.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://join.lunartech.ai/java-fundamentals">https://join.lunartech.ai/java-fundamentals</a></div>
<p>Master Machine Learning effortlessly with our free Handbook—a gateway to AI expertise. It's packed with insights and Python practices that promise to skyrocket your career. Claim your guide, forge your future, and join the ranks of AI leaders today.</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://join.lunartech.ai/machine-learning-fundamentals--3f64f">https://join.lunartech.ai/machine-learning-fundamentals--3f64f</a></div>
<p>Dive into essential Data Science concepts, ace interviews with ease, and navigate the job market like a pro. This book is your blueprint for tech success in 2023. You can <a target="_blank" href="https://downloads.tatevaslanyan.com/six-figure-data-science-ebook">grab your copy and start forging your path in the AI revolution today</a>.</p>
<h3 id="heading-connect-with-me">Connect with Me:</h3>
<ul>
<li><a target="_blank" href="https://ca.linkedin.com/in/vahe-aslanyan">Follow me on LinkedIn for a ton of Free Resources in CS, ML and AI</a></li>
<li><a target="_blank" href="https://vaheaslanyan.com/">Visit my Personal Website</a></li>
<li>Subscribe to my <a target="_blank" href="https://tatevaslanyan.substack.com/">The Data Science and AI Newsletter</a></li>
</ul>
<h2 id="heading-about-the-author">About the Author</h2>
<p>Vahe Aslanyan here, at the nexus of computer science, data science, and AI. Visit <a target="_blank" href="https://www.freecodecamp.org/news/p/61bdcc92-ed93-4dc6-aeca-03b14c584b30/vaheaslanyan.com">vaheaslanyan.com</a> to see a portfolio that's a testament to precision and progress. My experience bridges the gap between full-stack development and AI product optimization, driven by solving problems in new ways. </p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://www.vaheaslanyan.com/">https://www.vaheaslanyan.com/</a></div>
<p>With a track record that includes launching a leading data science bootcamp and working with industry top-specialists, my focus remains on elevating tech education to universal standards. </p>
<p>As I bring the 'Fundamentals of Java Handbook' to a close, I want to express my gratitude for your interest and trust. It's been a rewarding experience to condense a year's worth of field and academic knowledge into a manual that I hope will serve as a valuable tool in your programming journey. Thank you for joining me on this adventure, and I wish you the very best as you apply these teachings to achieve your coding aspirations.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Localization Guide – How to Translate Your Website Into Different World Languages [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ Welcome! In a global world where information is available to everyone in just a few clicks, adapting your website and resources to other languages and cultures is essential to succeed. This book will teach you the fundamentals of localization and how... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/localization-book-how-to-translate-your-website/</link>
                <guid isPermaLink="false">66b1f85841fdb67461b85342</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ i18n ]]>
                    </category>
                
                    <category>
                        <![CDATA[ localization ]]>
                    </category>
                
                    <category>
                        <![CDATA[ translation ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Estefania Cassingena Navone ]]>
                </dc:creator>
                <pubDate>Thu, 28 Sep 2023 18:17:44 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/09/Localization-Course-Handbook-Cover-Version-4.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>Welcome! In a global world where information is available to everyone in just a few clicks, adapting your website and resources to other languages and cultures is essential to succeed.</p>
<p>This book will teach you the fundamentals of localization and how to translate your website to reach a global community of users without any language barrier.</p>
<h2 id="heading-where-to-start">🔹 Where to Start</h2>
<p>But where do you start?</p>
<p>That is an important question that managers often ask themselves when they decide to adapt their products and go multilingual.</p>
<p>In this book, you will learn all the fundamentals of localization from a conceptual and practical point of view.</p>
<p>You will learn how to localize files, websites, games, and any other type of resource on <a target="_blank" href="https://crowdin.com/">Crowdin</a>, the cloud-based localization management platform that powers freeCodeCamp's localization effort.</p>
<p><strong>We will cover the following:</strong> </p>
<ul>
<li><a class="post-section-overview" href="#heading-freecodecamp-as-a-real-world-example">freeCodeCamp as a Real-World Example</a></li>
<li><a class="post-section-overview" href="#heading-a-localization-effort-by-humans-for-humans">A Localization Effort by Humans, for Humans</a></li>
<li><a class="post-section-overview" href="#heading-what-are-the-fundamentals-of-localization">What are the Fundamentals of Localization?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-localization">What is Localization?</a></li>
<li><a class="post-section-overview" href="#heading-translation-vs-localization">Translation vs Localization</a></li>
<li><a class="post-section-overview" href="#heading-importance-of-localization">Importance of Localization</a></li>
<li><a class="post-section-overview" href="#heading-localization-terminologies">Localization Terminologies</a></li>
<li><a class="post-section-overview" href="#heading-translation-vs-proofreading">Translating vs Proofreading</a></li>
<li><a class="post-section-overview" href="#heading-what-types-of-resources-can-be-localized">What Types of Resources Can Be Localized?</a></li>
<li><a class="post-section-overview" href="#heading-common-file-formats">Common File Formats</a></li>
<li><a class="post-section-overview" href="#heading-localization-phases-and-roles">Localization Phases and Roles</a></li>
<li><a class="post-section-overview" href="#heading-crowdin-fundamentals-for-localization-projects">Crowdin Fundamentals for Localization Projects</a></li>
<li><a class="post-section-overview" href="#important-terminologies-for-crowdin">Important Terminologies for Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-getting-started-with-crowdin">Getting Started with Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-crowdin-account">How to Create a Crowdin Account</a></li>
<li><a class="post-section-overview" href="#heading-how-to-customize-your-crowdin-profile">How to Customize your Crowdin Profile</a></li>
<li><a class="post-section-overview" href="#heading-how-to-create-a-project-on-crowdin">How to Create a Project on Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-project-overview">Project Overview</a></li>
<li><a class="post-section-overview" href="#heading-how-to-customize-your-project-settings-in-crowdin">How to Customize your Project Settings in Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-how-to-delete-a-project-in-crowdin">How to Delete a Project in Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-how-to-upload-files-to-your-crowdin-project">How to Upload Files to your Crowdin Project</a></li>
<li><a class="post-section-overview" href="#heading-how-to-start-translating">How to Start Translating</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-translation-editor">How to Use the Translation Editor</a></li>
<li><a class="post-section-overview" href="#heading-translation-editor-modes">Translation Editor Modes</a></li>
<li><a class="post-section-overview" href="#heading-how-to-switch-to-another-file">How to Switch to Another File</a></li>
<li><a class="post-section-overview" href="#heading-how-to-view-all-strings">How to View All Strings</a></li>
<li><a class="post-section-overview" href="#heading-how-to-translate-rtl-languages">How to Translate RTL Languages</a></li>
<li><a class="post-section-overview" href="#heading-how-to-download-the-translated-files">How to Download the Translated File(s)</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-translation-memory-tm">How to Use Translation Memory (TM)</a></li>
<li><a class="post-section-overview" href="#heading-glossary">Glossary</a></li>
<li><a class="post-section-overview" href="#heading-quality-assurance-qa-checks-in-crowdin">Quality Assurance (QA) Checks in Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-how-to-upload-existing-translations">How to Uploading Existing Translations</a></li>
<li><a class="post-section-overview" href="#heading-how-to-pre-translate-your-project">How to Pre-Translate your Project</a></li>
<li><a class="post-section-overview" href="#heading-offline-translation">Offline Translation</a></li>
<li><a class="post-section-overview" href="#heading-exploring-public-projects">Exploring Public Projects</a></li>
<li><a class="post-section-overview" href="#heading-crowdin-for-teams-and-organizations">Crowdin for Teams and Organizations</a></li>
<li><a class="post-section-overview" href="#heading-how-to-invite-project-members-and-contributors">How to Invite Project Members and Contributors</a></li>
<li><a class="post-section-overview" href="#heading-project-roles">Project Roles</a></li>
<li><a class="post-section-overview" href="#heading-how-to-assign-or-change-roles">How to Assign or Change Roles</a></li>
<li><a class="post-section-overview" href="#heading-project-managers">Project Managers</a></li>
<li><a class="post-section-overview" href="#heading-tasks">Tasks</a></li>
<li><a class="post-section-overview" href="#heading-project-reports">Project Reports</a></li>
<li><a class="post-section-overview" href="#heading-conversations-on-crowdin">Conversations on Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-crowdin-integrations-and-productivity-tools">Crowdin Integrations and Productivity Tools</a></li>
<li><a class="post-section-overview" href="#heading-how-to-translate-a-website-on-crowdin">How to Translate a Website on Crowdin</a></li>
<li><a class="post-section-overview" href="#heading-freecodecamps-translation-effort">freeCodeCamp's Translation Effort</a></li>
</ul>
<p>Are you ready? Let's begin!</p>
<h2 id="heading-freecodecamp-as-a-real-world-example">🔹 freeCodeCamp as a Real-World Example</h2>
<p>freeCodeCamp.org is a real-world example of an organization and open-source project that has embraced the concept of localization for reaching a global community.</p>
<p>Our coding curriculum is available in many languages, including:</p>
<ul>
<li>English.</li>
<li>Spanish.</li>
<li>Chinese.</li>
<li>Italian.</li>
<li>Portuguese.</li>
<li>Ukrainian.</li>
<li>Japanese.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/freecodecamp-language-dropdown-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to Choose a Language on freeCodeCamp.</em></p>
<p>Our community is actively working on translating freeCodeCamp into many world languages, including:</p>
<ul>
<li>Arabic.</li>
<li>Azerbaijani.</li>
<li>Bengali.</li>
<li>Chinese Simplified.</li>
<li>Dutch.</li>
<li>French.</li>
<li>German.</li>
<li>Hebrew.</li>
<li>Hindi.</li>
<li>Indonesian.</li>
<li>Italian.</li>
<li>Japanese.</li>
<li>Korean.</li>
<li>Nepali.</li>
<li>Persian.</li>
<li>Portuguese.</li>
<li>Romanian.</li>
<li>Spanish.</li>
<li>Swahili.</li>
<li>Turkish.</li>
<li>Ukrainian.</li>
<li>Urdu, and more.</li>
</ul>
<p>We have many world languages available for localization and we also run localized publications, YouTube channels, forums, and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/freecodecamp-crowdin-project.png" alt="Image" width="600" height="400" loading="lazy">
<em>Coding Curriculum localization project and available languages.</em></p>
<h2 id="heading-a-localization-effort-by-humans-for-humans">🔹 A Localization Effort by Humans, for Humans</h2>
<p>Our localization process is focused on what matters the most: our amazing community of learners who wake up every day excited about learning new skills.</p>
<p>We believe that language and culture should not be barriers to learning. Knowledge should be accessible worldwide.</p>
<p>This is why we started this process and why we'll continue our localization efforts until we reach our goal of guaranteeing access to knowledge around the world.</p>
<p>One of the key aspects of our localization process is that it is managed and run by humans, for humans. Translations are written and approved by members of our amazing community and staff.</p>
<p>Let's be honest, anyone can tell when a translation has been generated automatically. It's much more literal, it lacks the clarity, and it feels disconnected from the context and from the original tone of the text.</p>
<p>Human translators are much better at adapting languages, and translating sentences in a way that sounds more natural in different languages and cultures.</p>
<p>At freeCodeCamp, we have an amazing community of contributors who dedicate their time to translate our content and an amazing team of staff members who oversee the process with the ultimate goal of publishing high-quality translations for our learners.</p>
<p>Since we launched our localization effort, more than 2,000 translators and over 60 proofreaders have helped us accomplish our mission.</p>
<p>💡 <strong>Tip:</strong> If this sounds interesting to you and you would like to join freeCodeCamp's translation effort, please read our <a target="_blank" href="https://contribute.freecodecamp.org/#/index">contributing guidelines</a>. At the end of this article, you will find more information on our localization effort.</p>
<p>Managing such a large project with a worldwide community of contributors might seem complicated, right? How can we accomplish all of this as a non-profit organization?</p>
<p>You will get answers to those questions in this book.</p>
<p>We will cover all the fundamentals of localization, and the basic and advanced features of <a target="_blank" href="https://crowdin.com/">Crowdin</a>.</p>
<p>Are you ready? Let's begin.</p>
<h2 id="heading-what-are-the-fundamentals-of-localization">🔹 What are the <strong>Fundamentals</strong> of <strong>Localization?</strong></h2>
<p>We will start with an overview of the fundamentals of the localization process and the steps that you'll need to take to make sure that your product can be used without any language or cultural barriers.</p>
<h3 id="heading-what-is-localization">What is Localization?</h3>
<p>First of all, let's define <strong>localization</strong>.</p>
<p>According to the <a target="_blank" href="https://dictionary.cambridge.org/dictionary/english/localization">Cambridge Dictionary</a>, localization is defined as:</p>
<blockquote>
<p>The process of organizing a business or industry so that its main activities happen in local areas rather than nationally or internationally.</p>
</blockquote>
<p>In the context of products and services, localization basically means adapting them to the language and culture of a specific population. This also applies to software products because they need to be adapted to different cultures as well.</p>
<h3 id="heading-translation-vs-localization">Translation vs Localization</h3>
<p>You may be surprised to know that the concept of localization is different from the concept of translation. It's actually broader.</p>
<p>The <a target="_blank" href="https://dictionary.cambridge.org/dictionary/english/translation">Cambridge Dictionary</a> defines translation as:</p>
<blockquote>
<p>The activity or process of changing the words of one language into the words in another language that have the same meaning.</p>
</blockquote>
<p>Notice the key part of this definition: "changing the words to keep the same meaning."</p>
<p>Translation involves changing the words of a language into another language to keep their original meaning. It is very helpful but a bit limited because its goal is to say exactly the same thing in a different language.</p>
<p>However, localization can go beyond that to adapt the content better to another culture or country. </p>
<p>For example, localization is particularly helpful for marketing campaigns and ads that try to reach audiences and convince them to purchase their products. Certain cultures may accept certain colors better, or they may have local phrases or slangs that the local population is more familiar with.</p>
<p>In this case, localizing the campaign is better than writing a literal word-for-word translation.</p>
<p><strong>Continuous localization</strong> takes this concept one step further. It involves localizing a product continuously as it is updated or expanded in an agile product development cycle. It is often used to localize software products.</p>
<h2 id="heading-importance-of-localization">Importance of Localization</h2>
<p>Why should you localize your product or platform? Well, the world is very diverse, and different cultures have their distinctive customs and speak different languages. </p>
<p>Did you know that, according to the <a target="_blank" href="https://www.linguisticsociety.org/content/how-many-languages-are-there-world">Linguistic Society of America</a>, there are more than 6,000 languages in the world?</p>
<p>Among the top 20 most widely spoken languages in the world, we can find these:</p>
<ul>
<li>English.</li>
<li>Mandarin Chinese.</li>
<li>Hindi.</li>
<li>Spanish.</li>
<li>French.</li>
<li>Arabic.</li>
<li>Bengali.</li>
<li>Portuguese.</li>
<li>Urdu.</li>
<li>German.</li>
<li>Japanese.</li>
</ul>
<p>💡 <strong>Tip:</strong> You can find more information on languages by total number of speakers in <a target="_blank" href="https://en.wikipedia.org/wiki/List_of_languages_by_total_number_of_speakers">this article</a>.</p>
<p>A large proportion of the world's population is not bilingual. Not everyone around the world has the opportunity to learn and master English as a second language but every single person around the world is a potential user of your product or platform. </p>
<p>That is why localization can be so important for you.</p>
<p>For example, if you are creating an educational platform, you will be able to reach people and accomplish your mission at a global scale by localizing your website and content.</p>
<p>If you are building a commercial product or platform, every single person around the world can be a potential user. </p>
<p>Don't let language become a barrier to reach your users. Localization can be your best ally. </p>
<h2 id="heading-localization-terminologies">Localization Terminologies</h2>
<p>Now that you know why localization is so important, let's dive into some important terminologies that you'll come across very often in the context of translation and localization.</p>
<h3 id="heading-internationalization">Internationalization</h3>
<blockquote>
<p>The action of becoming or making something become international.<br>— <a target="_blank" href="https://dictionary.cambridge.org/dictionary/english/internationalization">Cambridge Dictionary</a>.</p>
</blockquote>
<p>In the context of localization for a software product, it also involves adapting the user interface for working with other languages and making sure that it is ready to be translated.</p>
<h3 id="heading-culturalized">Culturalized</h3>
<blockquote>
<p>Deriving from or imposed or conditioned by culture.<br>— <a target="_blank" href="https://www.merriam-webster.com/dictionary/culturalized">Merriam-Webster Dictionary</a>.</p>
</blockquote>
<p>Every culture has different traditions and vocabulary. Culture can play a key role in how communities embrace products, campaigns, and platforms. Understanding how to adapt them is very important to succeed.</p>
<h3 id="heading-pseudolocalization">Pseudolocalization</h3>
<p>The <em>pseudo</em> prefix is defined as:</p>
<blockquote>
<p>Pretended and not real.<br>— <a target="_blank" href="https://dictionary.cambridge.org/dictionary/english/pseudo">Cambridge Dictionary</a>.</p>
</blockquote>
<p>That is exactly what pseudolocalization is all about. It is a process creating fake translations that act as placeholders for the real translations in a platform or product.</p>
<p>You may ask: "Why would we ever need to use fake translations?"</p>
<p>The answer is that we use them to check if our software is ready to handle multiple languages even before the translation process begins.</p>
<p>Checking if a language that tends to have longer or shorter words works well with our current user interface and checking if right-to-left languages are displayed correctly are common use cases.</p>
<p>This process is also helpful to find any strings that may still be hard-coded in the project source files. You may need to move them to the resources file where you keep all your project strings.</p>
<p>That is the main purpose of pseudolocalization: checking if everything is ready to start translating.</p>
<h3 id="heading-machine-translation-mt">Machine Translation (MT)</h3>
<blockquote>
<p>The process of using artificial intelligence to automatically translate text from one language to another without human involvement.<br>— <a target="_blank" href="https://aws.amazon.com/what-is/machine-translation/">Amazon Web Services</a>.</p>
</blockquote>
<p>We will talk about this term in more detail because the localization management platform that we will use to translate our resources has this feature, and it can save us a lot time. </p>
<h3 id="heading-translation-memory-tm">Translation Memory (TM)</h3>
<blockquote>
<p>A database that stores "segments", which can be sentences, paragraphs or sentence-like units (headings, titles or elements in a list) that have previously been translated, in order to aid human translators.<br>— <a target="_blank" href="https://en.wikipedia.org/wiki/Translation_memory">Wikipedia</a>.</p>
</blockquote>
<p>With this feature, you can save previous translations and "reuse" them to save time.</p>
<p>💡 <strong>Tip:</strong> Note that the acronyms (MT and TM) are very similar and but they are different. Please take a moment to understand the differences between these two concepts because you'll see them in this book frequently.</p>
<h3 id="heading-large-language-models-llms">Large Language Models (LLMs)</h3>
<blockquote>
<p>Deep learning algorithms that can recognize, summarize, translate, predict, and generate content using very large datasets.<br>— <a target="_blank" href="https://www.nvidia.com/en-us/glossary/data-science/large-language-models/">Nvidia</a>.</p>
</blockquote>
<p>These terms are fundamental if you are looking to dive into translation and localization.</p>
<p>You may also find words that use numbers to represent abbreviations. They are called numeronyms.</p>
<ul>
<li><strong>L10n</strong>: this numeronym stands for Localization. The number 10 stands for the 10 letters between the <strong>l</strong> at the start and the <strong>n</strong> at the end.</li>
<li><strong>i18n</strong>: this numeronym stands for Internationalization (yes, it's a very long word!). The number 18 stands for the 18 letters between the <strong>i</strong> at the start and the <strong>n</strong> at the end.</li>
</ul>
<p>💡 <strong>Tip:</strong> Sometimes, you may find L10n with the L capitalized or you may find it in lowercase, like this: l10n. Capitalizing the L is helpful to distinguish it from the i in the i18n numeronym (they can look very similar in certain types of fonts).</p>
<h2 id="heading-translation-vs-proofreading">Translation vs Proofreading</h2>
<p>Another important aspect that you should also know is the difference between translating and proofreading. </p>
<p><strong>Translation</strong> involves changing the words from one language to another with the goal of keeping the same meaning.</p>
<p>But after translators have completed their work, the localization team will also need to review, edit, and approve the translations to make sure that everything is accurate and correct. This process of checking the translations is called <strong>proofreading</strong>.</p>
<p>Translating and proofreading are different stages of the localization process. We'll look these processes in more detail, and you will learn the steps involved and the role of team members in making sure that the content is localized correctly.</p>
<h2 id="heading-what-types-of-resources-can-be-localized">What Types of Resources Can Be Localized?</h2>
<p>When we talk about translation and localization, the first thing that comes to mind is translating files with text, right?</p>
<p>But this is not the only type of resource that we can localize. We can localize documents, spreadsheets, websites, games, dialogues, scripts, audio, video, graphics, and so on.</p>
<p>Think about podcasts and videos. They can be localized with voiceovers. We just need to translate their transcripts, replace the original audio and synchronize the translated narration.</p>
<p>Captions and subtitles can also be localized. This is a form of text too but it comes from a video source. You can see how different types of files can be closely related in the localization process.</p>
<p>Finally, we can localize graphics such as image files, visual marketing campaigns, ads, and more. </p>
<p>The main point to highlight here is that localization and translation are not limited to written resources. There are wide variety of resources that we can localize to reach a wider audience. </p>
<h2 id="heading-common-file-formats">Common File Formats</h2>
<p>In the last section, we talked about different types of resources that can be translated. Now let's talk about the file formats that you'll usually find in the context of translation. You may also find them in the localization management platform that we will be working on. </p>
<p>💡 <strong>Tip:</strong> Even if you do not use these file formats right now, it's always helpful to understand what they do and what they represent. They may come in handy in the future, or in cases where you find them in the documentation of a localization tool you are using.</p>
<h3 id="heading-comma-separated-values-csv-files">Comma-Separated Values (CSV) Files</h3>
<ul>
<li>File extension: <code>**.csv**</code></li>
<li>This is a text file format in which the values are separated by commas.</li>
<li>Stores tabular data such as numbers and text.</li>
<li>Each line usually represents one record.</li>
<li>Commonly used for data exchange and can be processed using programming languages.</li>
</ul>
<h3 id="heading-html-files">HTML Files</h3>
<ul>
<li>File extension: <code>**.html**</code></li>
<li>HTML stands for HyperText Markup Language.</li>
<li>It is used to represent the structure and content of a website.</li>
<li>If you open this file in a browser, you will see the content of the website.</li>
</ul>
<h3 id="heading-json-files">JSON Files</h3>
<ul>
<li>File extension: <code>**.json**</code></li>
<li>JSON stands for JavaScript Object Notation. </li>
<li>Stores data in a simple plain text format based on key-value pairs.</li>
<li>Used for data exchange, especially across the web because it is lightweight. </li>
</ul>
<h3 id="heading-markdown-files">Markdown Files</h3>
<ul>
<li>File extension: <code>**.md**</code></li>
<li>Used to create formatted text. </li>
<li>It is a lightweight markup language with a specific syntax.</li>
<li>Common applications include writing software documentation, blog posts, and articles.</li>
</ul>
<h3 id="heading-po-portable-object-files">PO (Portable Object) Files</h3>
<ul>
<li>File extension: <code>**.po**</code>.</li>
<li>Used by the <code>**gettext**</code> system, which is commonly used for writing multilingual programs. It is also widely used in the implementation of <code>**GNU gettext**</code>.</li>
<li><code>**gettext**</code> is a standard in many game development engines, like the Unreal Engine. It is used in many programming languages, including C, C++, PHP, and Python.</li>
</ul>
<h3 id="heading-text-file">Text File</h3>
<ul>
<li>File extension: <code>**.txt**</code></li>
<li>Used to store plain text. </li>
<li>It does not contain images or non-text characters.</li>
</ul>
<h3 id="heading-extensible-markup-language-xml">Extensible Markup Language (XML)</h3>
<ul>
<li>File extension: <code>**.xml**</code></li>
<li>Used to store, share, and reconstruct arbitrary data.</li>
<li>Commonly used to exchange data over the internet. </li>
<li>Many localization frameworks use XML. For example, Android uses an XML-based file format to store translatable text.</li>
</ul>
<h3 id="heading-xliff-files">XLIFF Files</h3>
<ul>
<li>File extension: <code>**.xliff**</code></li>
<li>XLIFF stands for XML Localization Interchange File Format.</li>
<li>Uses XML-based format.</li>
<li>Used to standardize the way the localizable data can be passed between localization tools.</li>
</ul>
<h3 id="heading-xlsx-files">XLSX Files</h3>
<ul>
<li>File extension: <code>**.xlsx**</code></li>
<li>Used to store data in spreadsheets.</li>
<li>It is an abbreviation of "Microsoft Excel Spreadsheet".</li>
</ul>
<h3 id="heading-resx-files">RESX Files</h3>
<ul>
<li>File extension: <code>**.resx**</code></li>
<li>Used by .NET applications for storing resources that can be localized.</li>
<li>Uses an XML-based file format.</li>
</ul>
<p>These are the most widely used file formats that you may find in localization projects but there are over hundreds of file formats that you can use.</p>
<p>Crowdin, the localization management platform that we will use on this book, supports more than 100+ file formats.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/supported-formats.png" alt="Image" width="600" height="400" loading="lazy">
<em>Overview of the <a target="_blank" href="https://store.crowdin.com/categories/file-formats">supported formats</a> in Crowdin.</em></p>
<h2 id="heading-localization-phases-and-roles">Localization Phases and Roles</h2>
<p>Awesome. Now that you know more about the types of files that you might find in a localization project, let's take a step further and see this process from a project management perspective.</p>
<p>What steps are required for localizing a project? Where should you start? Here are steps to help you answer those questions:</p>
<h3 id="heading-step-1-define-the-project-scope-and-goals">Step #1 - Define the project scope and goals</h3>
<p>Before you start to localize any file, it's important to take a moment to analyze your project's scope and goals. </p>
<p>Ask yourself:</p>
<ul>
<li>What is your target audience?</li>
<li>What are you trying to achieve by localizing your resources?</li>
<li>How will you achieve those goals?</li>
<li>What parts of your website, game, video, or resource do you need to localize?</li>
<li>Do you need to translate it or localize it (adapt it)? Sometimes, translation can be good enough.</li>
<li>If you need to adapt it to other cultures, how will you achieve this? </li>
<li>Will you seek advice from people who understand these cultures? If yes, how will you contact them?</li>
<li>If you speak other languages, can you translate the resources yourself or do you need to find help based on the complexities of your project? </li>
<li>What is your available budget? </li>
<li>Are your goals realistic given your current budget?</li>
</ul>
<p>You should also determine who is going to translate your resources:</p>
<ul>
<li>Will you be translating the resources yourself?</li>
<li>Will you involve your user-base or community in the translation effort?</li>
<li>Will you hire a team or use the services of a translation vendor? </li>
<li>Will you use automated processes like machine translation to translate or pre-translate resources with artificial intelligence?</li>
</ul>
<p>💡 <strong>Tip:</strong> Crowdin has an option to hire their localization services and services from their partners in the Crowdin Marketplace.</p>
<p>Defining clear and realistic goals can be very helpful for avoiding any unexpected challenges during the process.</p>
<p>Write down your goals and make sure that you have an outline of the steps that you need to take to start, execute, and complete the localization process.</p>
<h3 id="heading-step-2-create-the-source-files-to-be-localized">Step #2 - Create the source files to be localized</h3>
<p>Now that you have clear goals and a clear project scope in mind, having the project source files is a must. These are the files that your localization team will localize.</p>
<p>You should make sure that you have all the necessary source files and resources before you start the localization process. </p>
<p>Of course, you can always add new resources and content later in the process, but having a clear initial idea of the complexities of a project will be helpful later on in terms of the time management and budget required.</p>
<h3 id="heading-step-3-prepare-your-software-for-internationalization">Step #3 - Prepare your Software for Internationalization</h3>
<p>Before the localization process begins, you need to prepare your product for internationalization, which is very technology-specific.</p>
<p>This is especially true for software products. The tools that you use to internationalize a React.js application may be very different from the tools that you use for an Android application, an iOS application, or a game. </p>
<p>However, the approaches and concepts that you will use are essentially the same.</p>
<p>You need to think about how you will adapt your user interface and services to other languages. For example, some languages may have longer or shorter words than the source language and this can change how elements are displayed. </p>
<p>Making sure that everything looks like you intend it to is very important, even before translators and proofreaders get involved in the process.</p>
<p>Another key step is making sure that you have all your translatable text separated from your code. When you translate software, all translatable text is extracted into a resource file that can be shared with translators or uploaded to a localization management platform.</p>
<p>The Crowdin team recommends storing larger files, such as HTML pages, and email templates, in a separate directory and keeping one directory per target locale. They suggest that "if you are translating your content into 5 target languages, you would have 5 copies of your resource files with "UI labels" and 5 directories with all other assets like HTML files."</p>
<p>If you are developing a web application, you will also need to implement multilingual routing. Your application should allow users to select their preferred language. </p>
<p>To do this, you have two options. You can:</p>
<ul>
<li>Add the language code as part of the domain name. For example: <code>**fr.example.com**</code>.</li>
<li>Add the language code to the URL. For example: <strong><code>example.com/fr</code></strong>. </li>
</ul>
<p>This is recommended for Search Engine Optimization (SEO) purposes.</p>
<p>Your software should also be able to handle and display adapted numbers, dates, and currencies since localization may also involve adapting them to different formats for different cultures.</p>
<p>Context will also be very important. Many internationalization tools create resource files with only one key-value pair for each piece of text. They associate each piece of text in the source language with its corresponding translation.</p>
<p>But it is very important to make sure that the resource files of your project also include some contextual information of the content or elements around them. This can be very helpful for translators because they can choose the best translations possible based on the context around the string.</p>
<p>Finally, your application should also be able to handle pluralization correctly because different languages may have different plural forms. </p>
<p>💡 <strong>Tip:</strong> Some of these features may be available with the software development kit (SDK) that you are using, but you may need to add some of them using third-party libraries. It's always important to consider and check this.</p>
<h3 id="heading-step-4-assemble-a-team">Step #4 - Assemble a Team</h3>
<p>If you analyze the scope of the project and decide that you cannot complete it by yourself, then it's time to assemble a team.</p>
<p>You may hire a team or, if you are a non-profit organization like freeCodeCamp, use crowdsourcing to ask your community for help with the translations. You may be surprised by the number of generous and kind members of your community who will be willing to help you achieve your goals.</p>
<p>Once you have your team, you can assign them roles:</p>
<ul>
<li><strong>Translators</strong> use the localization management platform you choose to translate the resources. </li>
<li><strong>Proofreaders</strong> review, edit, and approve the translations. It's always helpful to review the translations to fix any typos or inconsistencies.</li>
<li><strong>Developers</strong> work on integrating the tools you choose to automate the localization process.</li>
<li><strong>Project Managers</strong> coordinate the tasks of the project. They assign translators and proofreaders to specific tasks to make sure that the project moves forward as fast as possible. </li>
</ul>
<h3 id="heading-step-5-choose-the-localization-tools">Step #5 - Choose the Localization Tools</h3>
<p>Choosing the right localization tool can be essential for reaching your goals. In the world of localization, there is a tool called Translation Management System (TMS).</p>
<p>This type of system is designed to help you automate repetitive tasks with the goal of optimizing your team's workflow. Humans will still have a role to play in the localization process, but with the help of a translation management system, they can achieve their goals much faster. </p>
<p>Usually, these systems can be integrated with content management systems (CMS) to import content automatically from other platforms, such as blogging platforms. Once it is imported, you can localize it and export it in order to publish the translated versions.</p>
<p>With the proper integrations, translation management systems can also check if there have been changes in the source files and import the new content automatically to start localizing it. </p>
<p>A real-world example of this process is right next to us — freeCodeCamp translates its source files in Crowdin. When a file from freeCodeCamp's curriculum changes, the new content is updated automatically in the system, so contributors can translate it and publish it very quickly. </p>
<p>Automating this process can be very helpful, especially for large organizations with different projects and files, so you do not have to keep track of these changes manually. </p>
<h3 id="heading-step-6-translate-the-resources">Step #6 - Translate the Resources</h3>
<p>If you already chose a translation management system or another helpful tool, then it's time to start translating the resources.</p>
<p>Usually, these platforms will divide the source content into what they call "strings", which are parts of the original text that you can translate. Translators will translate the strings and save their translations. </p>
<p>The software will take care of storing and combining the strings to replace them in the correct place in your file. </p>
<h3 id="heading-step-7-proofread-the-translations">Step #7 - Proofread the Translations</h3>
<p>Proofreading is one of the most important parts of the process because it's like the last quality assurance step made by humans. </p>
<p>Proofreaders should check if the translations are accurate, and if there is a better way to adapt them to the culture or language. They can also check if there are typos or misspelled words, and if the correct format is used. They can edit and approve the translated strings.</p>
<p>Sometimes they may find an extra comma, a missing emoji, an extra space, or a missing letter and those small details really count for the user experience, so this step should be taken very seriously. </p>
<h3 id="heading-step-8-export-the-localized-resources">Step #8 - Export the Localized Resources</h3>
<p>After proofreading and approving all the translations, the next thing to do is to export the final localized resources.</p>
<p>If your project is small, you may choose to do this manually. But if your project is more complex, you may choose to automate this process with different integrations on your localization management system.</p>
<p>For example, Crowdin has integrations with different platforms, including GitHub, Google Drive, Google Sheets, Dropbox, MailChimp, and so on.</p>
<p>If your translations are ready and approved and you set up a GitHub integration, the translated files will be updated automatically in your project's repository. You can even configure where the translated files will be stored.</p>
<h3 id="heading-step-9-check-for-changes">Step #9 - Check for Changes</h3>
<p>Projects and platforms can evolve over time. Files can change as you add new features and content. This is especially true for freeCodeCamp since we add new content and update our existing content on a regular basis. </p>
<p>So how can we handle these changes and still keep our platform properly localized?</p>
<p>Thanks to Crowdin, we can use integrations to be notified of the changes made to files and we can know if we have new strings to be translated. </p>
<p>When this happens, our amazing team of contributors and staff members will start translating and proofreading the new strings, repeating this cycle every time we need to bring the translation percentage back to 100%.</p>
<h2 id="heading-crowdin-fundamentals-for-localization-projects">🔹 <strong>Crowdin Fundamentals for Localization Projects</strong></h2>
<p>Now that we covered the fundamental concepts of localization, we'll use them in the localization management platform that powers freeCodeCamp's localization effort.</p>
<h3 id="heading-what-is-a-localization-management-platform">What is a Localization Management Platform?</h3>
<p>This is a platform that helps you and your team to localize your resources, products, and platforms efficiently through automation, cloud-based services, and integrations with other platforms.</p>
<p>We talked about translation management platforms before, right?</p>
<p>Localization management platforms are very similar but they help you to localize your products, which is even broader than just translating the text word by word. </p>
<h3 id="heading-what-is-crowdin">What is Crowdin?</h3>
<p>Crowdin is a localization management platform that can be described as:</p>
<blockquote>
<p>A cloud-based solution that streamlines localization management for your team. (<a target="_blank" href="https://crowdin.com/">Source: Crowdin</a>)</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-landing-page.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin's landing page.</em></p>
<p>The team mentions that, "It's the perfect place to effectively manage all of your multilingual content. It allows you to streamline the localization process and keep your workflow agile."</p>
<p>This platform is also great for teams and organizations who are planning to localize their content into multiple languages.</p>
<p>This is <a target="_blank" href="https://crowdin.com/">Crowdin's official website</a> in case you would like to check it out:</p>
<div class="embed-wrapper"><div class="embed-loading"><div class="loadingRow"></div><div class="loadingRow"></div></div><a class="embed-card" href="https://crowdin.com/">https://crowdin.com/</a></div>
<p>You will be applying your knowledge of localization on this platform, and you'll even learn how to localize a website in just a few minutes with Crowdin's services and integrations. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-workflow.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin Workflow. Image taken from Crowdin's <a target="_blank" href="https://crowdin.com/">official website</a>.</em></p>
<h3 id="heading-the-founder-of-crowdin">The Founder of Crowdin</h3>
<p><a target="_blank" href="https://crowdin.com/page/about-crowdin">Serhiy Dmytryshyn</a> is the founder and CEO of Crowdin. He launched the company in 2009 and it now has over 2 million registered users in over 160 countries.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Founder-and-CEO-of-Crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://crowdin.com/page/about-crowdin">Serhiy Dmytryshyn</a>, founder and CEO of Crowdin.</em></p>
<p>We had the opportunity to meet with him and ask him how he would describe Crowdin in five words. His answer was:</p>
<blockquote>
<p>Continuous Localization for Modern Companies.<br>— Serhiy Dmytryshyn</p>
</blockquote>
<p>His vision is for Crowdin to be the best platform for localizing products that are constantly evolving and for projects that may never have a final version because they will be continuously improved, expanded and updated, such as software products.</p>
<p>freeCodeCamp is an example of this. We are constantly adding and updating our content, which means that we also need an efficient and agile localization process to keep our platform accessible and updated for our global community.</p>
<p>The <a target="_blank" href="https://crowdin.com/page/about-crowdin">main goal</a> of Crowdin is to:</p>
<blockquote>
<p>Expand the potential of agile localization.</p>
</blockquote>
<p>But what is agile localization? Let's see.</p>
<h3 id="heading-what-is-agile-localization">What is Agile Localization?</h3>
<p>Agile localization is a process in which localization is incorporated into an agile product development cycle, with the goal of localizing the product as quickly as possible as it evolves.</p>
<p><strong>💡 Tip:</strong> An agile product development cycle is a cycle in which a product is constantly being updated in an iterative approach.</p>
<p>An agile localization process differs from the traditional localization process in that the translations are not only written once and then added to the final product. They are continuously added and updated as the product changes.</p>
<p>This sound great, right?</p>
<p>But constant updates also require constant management, team work, file uploads and downloads, platform deployments, and so on. </p>
<p>This process could become complicated very quickly if your team does not have the right tools, but with a localization management platform like Crowdin, you and your team can save time and accomplish your goals more efficiently.</p>
<h3 id="heading-advantages-of-crowdin">Advantages of Crowdin</h3>
<p>Let's see some of the reasons why you should use Crowdin:</p>
<ul>
<li>You can connect your project with external services through integrations to automate part of the localization process.</li>
<li>You can store your translations on their cloud-based services and grant access to team members and contributors from all around the world. </li>
<li>You can generate machine translations automatically when a resource is created and ask translators to check and edit them to save time.</li>
<li>Your team can check the quality and format of the translations with Crowdin's quality assurance, spellchecking, and proofreading features.</li>
<li>You can generate reports, communicate with team members internally, assign roles and permissions, invite new members, and much more.</li>
</ul>
<p>Basically, it's a platform that will make the localization process much easier for you and your team.</p>
<h3 id="heading-crowdins-free-plan">Crowdin's Free Plan</h3>
<p>One great thing about Crowdin is that they offer a completely free plan with all the essential features for translators to start localizing their content.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-free-plan.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin's free features.</em></p>
<p>Yes, it's free! You only need to create an account and you will be able to: </p>
<ul>
<li>Create unlimited public projects that everyone can see and contribute to. </li>
<li>Add unlimited translators to your public projects.</li>
<li>Create one private project.</li>
<li>Host up to 60,000 words in your translations. </li>
<li>Use helpful features for improving translators' efficiency. </li>
<li>Add one integration to your project (we will talk about integrations in just a moment). </li>
</ul>
<p>When you sign up and create your account, you can also start a 14-day free trial of their Team plan and they also have a 30-day trial period for their Business plan.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/free-trial.png" alt="Image" width="600" height="400" loading="lazy">
<em>Frequently Asked Question (FAQ).</em></p>
<p>Crowdin also has <a target="_blank" href="https://crowdin.com/pricing#annual">other plans</a> to fit your needs. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-pricing.png" alt="Image" width="600" height="400" loading="lazy">
<em>The plans that you can choose from.</em></p>
<h3 id="heading-crowdin-for-open-source-projects-and-educational-institutions">Crowdin for Open-Source Projects and Educational Institutions</h3>
<p>As a non-profit organization, freeCodeCamp has a special license that Crowdin grants to open-source projects and educational institutions to support their mission.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-for-nonprofits.png" alt="Image" width="600" height="400" loading="lazy">
<em>Frequently Asked Question (FAQ).</em></p>
<p>If you represent an open source project or an educational institution, you can contact Crowdin for an <a target="_blank" href="https://crowdin.com/page/open-source-project-setup-request">Open Source Request</a> or an <a target="_blank" href="https://crowdin.com/page/academic-license-project-setup-request">Academic License Request</a>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-for-open-source.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin for Open Source.</em></p>
<p>The Crowdin team will assist you and your organization.</p>
<h2 id="heading-important-terminologies-for-using-crowdin">Important Terminologies for Using Crowdin</h2>
<p>Before we dive into practicing with the features of Crowdin, let's talk a little bit about important terminologies for working with localization management platforms.</p>
<p>You will find these terms very often in the sections that follow, so let's talk about them in detail. </p>
<h3 id="heading-strings">Strings</h3>
<p>When you upload a resource to Crowdin, the platform has to divide the text into smaller "segments" that can be translated and saved individually until all the translations are ready. These segments of the original text are what we call "strings". After they have been translated and approved, they cab be combined to generate the localized version of the resource. </p>
<p><strong>💡 Tip:</strong> You can think of strings as the smallest units of the translation process. We do not translate the text word by word. We translate them string by string.</p>
<h3 id="heading-source-language">Source language</h3>
<p>The source language is the original language of the resource. For example, freeCodeCamp's source language is English since the curriculum and documentation are created in English. </p>
<h3 id="heading-target-language">Target language</h3>
<p>This is the language that our resources are translated into. For example, freeCodeCamp's projects has different target languages because we translate our resources into different languages.</p>
<h3 id="heading-translation-memory-tm-1">Translation Memory (TM)</h3>
<p>This is like a database where we store all the previously translated "segments" of our project. We may store sentences, paragraphs, or other units of the text with their matching source segments. The goal is to reuse the same translations later on in projects when we find them. It is a feature that can save you a lot of time because it only takes a few seconds to choose a saved translation. We can adapt them if we need to but we'll still have a foundation to work on.</p>
<h3 id="heading-machine-translation-mt-1">Machine Translation (MT)</h3>
<p>This process involves a computer software translating the resources of your project automatically without any human intervention. Usually, artificial intelligence and machine learning are part of this process. Translators and proofreaders can then take the computer-generated translations and adapt them or fix them as needed.</p>
<p>💡 <strong>Tip:</strong> Please note that translation memory (TM) and machine translation (MT) are very different even thought their acronyms are very similar. This may be a bit confusing at first, but always remember that "memory" refers to a translation's database and "machine" refers to an automated translation process. </p>
<h3 id="heading-qa-checks">QA Checks</h3>
<p>QA means "Quality Assurance". This is the process of checking if the translations have the correct format and spelling. Crowdin has many QA features that can help your team find and fix any potential errors.</p>
<h3 id="heading-glossary">Glossary</h3>
<p>This is a database of important terms in your project with their corresponding meanings. The goal of creating and maintaining a glossary is to give your translators more context about the terms and help them choose the most accurate translations. </p>
<h3 id="heading-screenshot">Screenshot</h3>
<p>A picture of what you can see on your computer screen at a particular moment. This is stored as an image file.</p>
<h3 id="heading-crowdsourcing">Crowdsourcing</h3>
<p>This is a localization practice based on community cooperation. Basically, if you are an organization and your goal is to translate your resources into many languages, you can ask help from your community. freeCodeCamp's translation effort is an example of crowdsourcing.</p>
<h3 id="heading-pre-translation">Pre-translation</h3>
<p>This is an automated technique that you can use in Crowdin to pre-translate your project automatically using either Machine Translation (MT) or Translation Memory (TM). Then, your translators can check the computer-generated translations and adapt them as needed.</p>
<h3 id="heading-integrations">Integrations</h3>
<p>These are connections that you can make between Crowdin and other applications or services, such as GitHub, Google Drive, Google Sheets, and so on. This is how freeCodeCamp keeps its GitHub repository translated. When we add new strings, they are automatically uploaded to Crowdin and translators can start working on them.</p>
<h3 id="heading-webhooks">Webhooks</h3>
<p>These are automated "messages" that an application or platform will send to another application or platform when specific events happen. In Crowdin, you can send them when translations are completed, when files are proofread, and so on.</p>
<h3 id="heading-command-line-interface-cli">Command-line Interface (CLI)</h3>
<p>This is a text-based user interface that we can use to interact with a computer program by entering commands. Crowdin has a command-line interface (CLI) called the Crowdin Console Client that allows you to synchronize localization resources with your project.</p>
<h3 id="heading-application-programming-interface-api">Application Programming Interface (API)</h3>
<p>This is an intermediary that allows two applications to communicate with each other by sending information following specific protocols. Crowdin also has an API that can help you to integrate localization into your development process.</p>
<h3 id="heading-custom-variables">Custom Variables</h3>
<p>In Crowdin, you can specify variables that should not be translated. They will be highlighted in the source strings that translators can see. To enable this feature, you will need to contact the support team at Crowdin.</p>
<h2 id="heading-getting-started-with-crowdin">Getting Started with Crowdin</h2>
<p>After this detailed but super important introduction into the fundamentals of localization, now it's time to dive into practice and start working on Crowdin. </p>
<h3 id="heading-how-to-create-a-crowdin-account">How to Create a Crowdin Account</h3>
<p>If your goal is to create a project on Crowdin, you'll need to create an account if you don't have one already.</p>
<p>To do that, go to <a target="_blank" href="https://crowdin.com/">crowdin.com</a>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-landing-page-signed-out.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin Landing page.</em></p>
<p>Click on Sign up.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/sign-up.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sign up Button.</em></p>
<ol start="3">
<li>Create your account by filling and submitting the form. You will need to enter your email, username, and password. You will also have to agree to the terms by checking the checkbox.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/sign-up-form.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sign up form.</em></p>
<p><strong>💡 Tip:</strong> After signing up, you will need to confirm your email address. You will receive an email from Crowdin with a link that you can click on to go to your profile. You should see a confirmation message saying that your email was confirmed.</p>
<p>After signing up (or logging in if you already have an account), you will see your new Crowdin profile where you can manage your projects, team members, workflows, activity, and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/new-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>New Crowdin Profile.</em></p>
<p>🎉 Congratulations! Now you have your Crowdin account and you are ready to start customizing your profile. </p>
<h3 id="heading-how-to-customize-your-crowdin-profile">How to Customize your Crowdin Profile</h3>
<p>To customize your profile:</p>
<p>Click on the small profile image at the top right, and choose "Settings" from the dropdown menu.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-menu.png" alt="Image" width="600" height="400" loading="lazy">
<em>Customize your profile.</em></p>
<p>You will see your profile and the information that you can customize, such as your:</p>
<ul>
<li>Profile image.</li>
<li>Full name, username, and email.</li>
<li>Company and job title.</li>
<li>Gender.</li>
<li>A brief description of you.</li>
<li>Language, timezone, and time format.</li>
<li>Preferred languages.</li>
<li>Appearance (light, dark, or based on your local time).</li>
<li>Privacy. By default, your profile is public. Check this option if you would like to make your profile private.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/black-profile-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Account Settings &gt; Profile.</em></p>
<p>💡 <strong>Tip:</strong> From this page, you can also delete your account. You will see a red button at the bottom and a warning of the consequences of doing so. You should only click this button if you are absolutely sure that you need to delete all your projects and the data associated with them.</p>
<h3 id="heading-how-to-create-a-project-on-crowdin">How to Create a Project on Crowdin</h3>
<p>Now that you know how to customize your profile, let's create a project. You can create a project from your profile page. </p>
<p>If you are in a different part of the platform, you can go back to your profile by clicking on the your small profile image at the top right and click on "Profile", like you can see in the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/go-back-to-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Profile page.</em></p>
<p>To create a project, click on the "Create Project" button (the green one or the gray one, they are both equivalent).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-a-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create Project (green button).</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-a-profile-2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create Project (gray button).</em></p>
<p>You will see a page where you can fill the basic information about your project, such as:</p>
<ul>
<li>Name.</li>
<li>Project address. This is the URL for your project. If your project address has multiple words, separate them with dashes (-).</li>
<li>Privacy settings (public or private).</li>
<li>The source language.</li>
<li>The target language(s).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-a-project.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a Project.</em></p>
<p>💡 <strong>Tip:</strong> Your project address must be unique. It will be filled automatically when you write your project name. If it is already taken by another user, you will see a red warning and you will need to choose a different one.</p>
<p>You can choose as many target languages as you need. Just check their checkboxes and they will be added.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/target-languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Target languages.</em></p>
<p>This what you should see when you start choosing your target languages:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/target-languages-selected.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing some target languages.</em></p>
<p>You also have an option to pre-fill the selection with the top 30 languages without selecting them manually:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-top-30-languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select Top 30 languages.</em></p>
<p>💡 <strong>Tip:</strong> You can also create custom languages or copy the selection that you made for another project.</p>
<p>If you choose to add a custom language, you will see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/adding-a-custom-language.png" alt="Image" width="600" height="400" loading="lazy">
<em>Adding custom languages.</em></p>
<p>Since this is a completely custom language, you will have to specify:</p>
<ul>
<li>The language name.</li>
<li>If it is a dialect of another language.</li>
<li>The code for that language on Crowdin.</li>
<li>Its three-letter code.</li>
<li>Its locale-code.</li>
<li>If the text will be written from left to right or from right to left. </li>
<li><p>The plural form.</p>
</li>
<li><p>After filling all these information, you are ready to create your project. Just click on the "Create Project" button at the bottom of the page. </p>
</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-project.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>💡 <strong>Tip:</strong> You can also click "Cancel" and go back to this page if you want to start over.</p>
<p>Now you should able to see your project. Of course, it will be empty at first but don't worry. We will take care of that in just a moment. 😉</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard.png" alt="Image" width="600" height="400" loading="lazy">
<em>New Project.</em></p>
<h3 id="heading-project-overview">Project Overview</h3>
<p>Let's have a quick tour of the project.</p>
<p>First, you can see the name of the project with its current privacy settings. My demo project is private. You can create unlimited public projects or one private project with your free Crowdin account.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard-name.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next to the project name, you will see two buttons: "Invite People" and "Buy Translations". </p>
<p>You can invite team members to join your project (we'll cover how to do that in this book) and you can also buy translations from Crowdin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard-buttons.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can also find all the tabs you need to access the available tools for your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard-tabs.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You will be in the "Sources" tab by default, where you can see the source files that you have uploaded and the strings of your project. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-dashboard-sources.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p><strong>💡 Tip:</strong> You will also be able to create folders and add files.</p>
<p>Let's see the other tabs:</p>
<h4 id="heading-dashboard-tab">Dashboard Tab</h4>
<p>This is where you will see a list of the project's target languages.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/dashboard-target-languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dashboard tab.</em></p>
<h4 id="heading-translations-tab">Translations Tab</h4>
<p>This is where you can upload existing translations, download your translations as a zip file, target file bundles, and set up over-the-air content delivery.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translations-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translations tab.</em></p>
<h4 id="heading-screenshots-tab">Screenshots Tab</h4>
<p>This is where you can upload screenshots of your project to help your translators with more context about the strings they are translating. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/screenshots-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshots tab.</em></p>
<h4 id="heading-tasks-tab">Tasks Tab</h4>
<p>This is where you can create and assign tasks to your team members.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tasks-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks tab.</em></p>
<h4 id="heading-members-tab">Members Tab</h4>
<p>This is where you can see all the members of your project with their respective roles, when they joined the project, and the actions that you can take for each member.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/members-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Members tab.</em></p>
<h4 id="heading-integrations-tab">Integrations Tab</h4>
<p>This is where you can add integrations to your project and see all the integrations that your project currently has.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/integrations-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Integrations tab.</em></p>
<h4 id="heading-reports-tab">Reports Tab</h4>
<p>This is where you can see and generate reports on the activity of your project, including translation and proofreading.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/reports-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reports tab.</em></p>
<h4 id="heading-activity-tab">Activity Tab</h4>
<p>This is where you can see the project activity.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/activity-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Activity tab.</em></p>
<h4 id="heading-discussions-tab">Discussions Tab</h4>
<p>This is where you can open discussion topics to discuss aspects of the project with your team. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/discussions-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Discussions tab.</em></p>
<h4 id="heading-tools-tab">Tools Tab</h4>
<p>This is where you can find more information on the Command Line Tool, API, Webhooks, and Crowdin in-context (a tool to translate web applications with a real-time preview).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tools-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tools tab.</em></p>
<h4 id="heading-settings-tab">Settings Tab</h4>
<p>This is where you can customize the project settings. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Settings tab.</em></p>
<p>Talking about project settings, let's dive into the settings that you can customize for your project.</p>
<h3 id="heading-how-to-customize-your-project-settings-in-crowdin">How to Customize your Project Settings in Crowdin</h3>
<p>You will find different categories of project settings.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-tab-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Settings tab.</em></p>
<h4 id="heading-general-settings">General Settings</h4>
<p>The general settings include:</p>
<ul>
<li>Name.</li>
<li>Public description.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/general-settings-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>General Settings.</em></p>
<ul>
<li>Branding, including a custom domain and a project logo.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/branding-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Branding Settings.</em></p>
<ul>
<li>Badges to show the progress of the localization process.</li>
<li>An option to delete the project.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-18-at-8.25.48-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Badges and Deleting a Project.</em></p>
<h4 id="heading-privacy-and-collaboration">Privacy and Collaboration</h4>
<p>In this category, you will find settings to manage the privacy and notifications of your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/privacy-and-collaboration.png" alt="Image" width="600" height="400" loading="lazy">
<em>Privacy and Collaboration.</em></p>
<p>You can manage your project's visibility in the project visibility settings. You can set your project to be public or private. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-visibility.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Next, we have the privacy settings. You can read a short description of each one of these settings below each corresponding item. To enable a setting, check its checkbox.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/privacy-settings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Default privacy settings. You can customize these to fit your needs.</em></p>
<p>Finally, the notifications settings for translators, project managers, and developers can also be customized. Just check the notifications that you would like to enable.  </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-18-at-8.29.36-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Notifications settings.</em></p>
<h4 id="heading-languages">Languages</h4>
<p>In the languages category, you can change the source and target languages of your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/languages-settings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Languages settings.</em></p>
<h4 id="heading-quality-assurance-qa-checks">Quality Assurance (QA) Checks</h4>
<p>I promised you that this would be important, right? Here we are. In the quality assurance (QA) category, you can enable QA Checks and choose which specific QA checks you would like to have in your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-checks.png" alt="Image" width="600" height="400" loading="lazy">
<em>QA Checks category.</em></p>
<p>Crowdin <a target="_blank" href="https://support.crowdin.com/qa-checks/">mentions</a> that:</p>
<blockquote>
<p>The main aim of quality assurance (QA) checks is to help you efficiently handle different language-specific aspects in translations and ensure they are formatted the same way as the source strings and will fit the UI just as well. Some typical QA check issues include missed commas, extra spaces, or typos.  </p>
<p>It’s recommended to review and resolve all QA check issues before building your project and downloading translations.</p>
</blockquote>
<p>These quality assurance checks include:</p>
<ul>
<li>Empty translations.</li>
<li>Length issues.</li>
<li>Tags mismatch.</li>
<li>Spaces mismatch.</li>
<li>Variables mismatch.</li>
<li>Punctuation mismatch.</li>
<li>Character case mismatch.</li>
<li>Special characters mismatch.</li>
<li>"Incorrect translation" issues marked by project members.</li>
<li>Spelling mistakes.</li>
<li>ICU (International Components for Unicode) Syntax Errors.</li>
<li>Consistent terminology that follows the project glossary.</li>
<li>Duplicate translation.</li>
<li>FTL syntax.</li>
<li>Android syntax.</li>
</ul>
<p>After you select the QA Checks that you would like to enable, just click on the "Save" button and your changes will be saved.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/save-qa-checks.png" alt="Image" width="600" height="400" loading="lazy">
<em>Save Button.</em></p>
<h4 id="heading-translation-memories">Translation Memories</h4>
<p>You will also find a category for Translation Memories settings.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-memories.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation Memories category.</em></p>
<p>We will talk about Translation Memories in detail later on, but know that this is where you can customize all the settings of this helpful feature.</p>
<h4 id="heading-glossaries">Glossaries</h4>
<p>You can also manage your glossaries from the Glossaries category. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossaries.png" alt="Image" width="600" height="400" loading="lazy">
<em>Glossaries category.</em></p>
<p>You can check your assigned glossaries and click on links to view the records of each glossary. At the top, you will also find a link to the <a target="_blank" href="https://crowdin.com/store/apps/glossary-translate-app">Translate Glossary App</a>.</p>
<h4 id="heading-import">Import</h4>
<p>In Crowdin, you can import source strings and you can customize settings such as how to handle duplicate strings and how to count the words. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/import-category.png" alt="Image" width="600" height="400" loading="lazy">
<em>Import settings.</em></p>
<h4 id="heading-export">Export</h4>
<p>The export category has helpful settings for exporting your translated files.</p>
<p>You can choose to:</p>
<ul>
<li>Save context information in the files.</li>
<li>Skip untranslated strings.</li>
<li>Skip untranslated files.</li>
<li>Export only approved translations.</li>
<li>Automatically fill in regional dialects.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/export.png" alt="Image" width="600" height="400" loading="lazy">
<em>Export settings.</em></p>
<h4 id="heading-labels">Labels</h4>
<p>Labels can be helpful for adding context to strings and organizing them by topics. They can be useful when you want to search for specific strings. </p>
<p>You can add labels from this category in the settings:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/labels.png" alt="Image" width="600" height="400" loading="lazy">
<em>Labels settings.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/creating-a-label.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a New Label.</em></p>
<h4 id="heading-parser-configuration">Parser Configuration</h4>
<p>With the Parser Configuration, you can configure how Crowdin imports and exports selected file types to fit your needs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/parser-configuration.png" alt="Image" width="600" height="400" loading="lazy">
<em>Parser Configuration category.</em></p>
<h4 id="heading-file-processors">File Processors</h4>
<p>The last group in the settings is File Processors, which allows you to customize how to process supported file formats.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/file-processors.png" alt="Image" width="600" height="400" loading="lazy">
<em>File Processors category.</em></p>
<h2 id="heading-how-to-delete-a-project-in-crowdin">How to Delete a Project in Crowdin</h2>
<p>If you ever need to delete a project, remember that you can do so by going to the "Setting" tab and click on the "General" tab.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-tab-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Settings &gt; General.</em></p>
<p>At the bottom, you will find a red "Delete Project" button. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/delete-a-project-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Delete project.</em></p>
<h2 id="heading-how-to-upload-files-to-your-crowdin-project">How to Upload Files to your Crowdin Project</h2>
<p>Now that you know how to customize your project settings, let's actually add a file to the project. You can either upload your project files manually or automate this process through integrations. </p>
<h3 id="heading-how-to-upload-files-manually">How to Upload Files Manually</h3>
<p>Let's upload a sample PDF file with text and images.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-pdf-document-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Our Demo PDF File. We will translate this in Crowdin.</em></p>
<p>To upload files:</p>
<ol>
<li>Go to your project.</li>
<li>Go to the "Sources" tab. </li>
<li>Click on the green "Add File" button or on the gray "Upload Files" button (please see the screenshot below).</li>
<li>Choose the file that you need to upload from your file system. </li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-files-sources.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload files or use sample files.</em></p>
<p>💡 <strong>Tip:</strong> To explore how Crowdin works, you can also add Crowdin sample files by clicking on the "Use Samples" button.</p>
<p>After uploading your file, you will see it listed:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-files.png" alt="Image" width="600" height="400" loading="lazy">
<em>Uploading a file.</em></p>
<p>You may need to wait a few seconds before the file is processed. Then, you will see the total string count for your file.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-finished.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload finished.</em></p>
<p>💡 <strong>Tip:</strong> You can also drag and drop your file into the files area in the "Sources" tab and your file will be uploaded automatically.</p>
<p>If you click on the three small dots on the right, you will see more options for that file, including:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/uploaded-file-options.png" alt="Image" width="600" height="400" loading="lazy">
<em>Additional Options.</em></p>
<ul>
<li>Settings.</li>
<li>Progress.</li>
<li>View strings.</li>
<li>Open in Editor.</li>
<li>Download source.</li>
<li>Rename.</li>
<li>Delete.</li>
</ul>
<h3 id="heading-how-to-upload-files-automatically">How to Upload Files Automatically</h3>
<p>One of the key aspects of Crowdin is how easy it is to connect it to other services through integrations, to automatically upload your files and synchronize your translations. </p>
<p>For example, freeCodeCamp has a GitHub integration set up, so we can automatically synchronize the files of our project when we add new strings that have to be translated on Crowdin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/github-integration-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub integration.</em></p>
<p>You can also find hundreds of integrations on the <a target="_blank" href="https://store.crowdin.com/">Crowdin store</a> to connect your project to external services. </p>
<p>Crowdin also has an Application Programming Interface (API) for developers. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-api.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Crowdin API <a target="_blank" href="https://developer.crowdin.com/api/v2/">Documentation</a>.</em></p>
<p>The Crowdin team <a target="_blank" href="https://developer.crowdin.com/api/v2/">describes</a> it as:</p>
<blockquote>
<p>A full-featured RESTful API that helps you to integrate localization into your development process. The endpoints that we use allow you to easily make calls to retrieve information and to execute actions needed.</p>
</blockquote>
<p>With this API, you can:</p>
<ul>
<li>Create projects for translation.</li>
<li>Add and update files.</li>
<li>Download translations, and more.</li>
</ul>
<p>It is a great way to automate your localization process. You can learn more about the Crowdin API on the <a target="_blank" href="https://developer.crowdin.com/api/v2/">official documentation</a>.</p>
<p>And the third option to upload files automatically is to use the Command-Line Interface (CLI). </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-cli-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Crowdin Command-line Interface (CLI).</em></p>
<p>With this interface, you can:</p>
<ul>
<li>Automate the process of uploading files.</li>
<li>Download translations automatically and save them in the correct locations. </li>
<li>Upload existing translations.</li>
<li>Integrate Crowdin with other tools like Git.</li>
</ul>
<p>To learn more about the Crowdin CLI, check out <a target="_blank" href="https://www.youtube.com/watch?v=0duN4khpWjM">this tutorial</a> created by the Crowdin team.</p>
<p>Now that you know how to upload your files to Crowdin manually and automatically, let's see how you and your team can start translating.</p>
<h2 id="heading-how-to-start-translating">How to Start Translating</h2>
<p>Once your file is uploaded, it's time to start translating. You may start translating it yourself or you ask your team to start working on the translations. </p>
<p>💡 <strong>Tip:</strong> You can assign specific files to your translators and proofreaders with the tasks feature.</p>
<p>Let's assume that you are translating the files yourself. </p>
<p>To start, you need to go to the project's Dashboard tab and select the language that you will be translating your file into from the list of target languages that you chose when you created the project.</p>
<p>I will choose Spanish for this demo.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/list-of-target-languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Dashboard.</em></p>
<p>You will see all your project files for that specific target language. </p>
<p>On the language page, you can check the translation and proofreading progress of each file, translate and proofread, and upload or download your translations and source files. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-files-in-spanish.png" alt="Image" width="600" height="400" loading="lazy">
<em>List of files to be translated into Spanish.</em></p>
<p>You can click on the name of the file that you would like to translate. This will take you to the Translation Editor and you will see your file in the preview.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor.</em></p>
<p>When upload a file, Crowdin divides it into strings. This process may require certain format conversions based on the type of file that you are uploading.</p>
<p>According to the <a target="_blank" href="https://support.crowdin.com/supported-formats/#converted-file-formats">Crowdin documentation</a>:</p>
<blockquote>
<p>On import, some file formats are automatically converted into other formats to be further parsed and processed.   </p>
<p>You can see the list of the initial file formats and the file formats they’re being converted into in the table below.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/file-formats-table.png" alt="Image" width="600" height="400" loading="lazy">
<em>File formats conversion. Image taken from the <a target="_blank" href="https://support.crowdin.com/supported-formats/#converted-file-formats">Crowdin documentation</a>.</em></p>
<p>We can see that PDF files are converted into DOCX files, the type of file that we usually create in a text editor.</p>
<p>Then, to export the file, <a target="_blank" href="https://support.crowdin.com/supported-formats/#converted-file-formats">Crowdin also mentions</a> that:</p>
<blockquote>
<p>By default, we export the translations in the same format as the source files. For example, if you upload an XML file to Crowdin, you’ll have the XML file exported.</p>
</blockquote>
<h2 id="heading-how-to-use-the-translation-editor">How to Use The Translation Editor</h2>
<p>This is the layout of the translation editor that you will see by default when you click on a file. It is called the Comfortable Mode.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor.</em></p>
<p>It has four main sections:</p>
<ul>
<li>The left sidebar (in purple below).</li>
<li>Middle-top area (in yellow below).</li>
<li>Middle-bottom area (in orange below).</li>
<li>Right sidebar (in blue below).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor-sections.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor in Comfortable Mode.</em></p>
<p>Let's talk about each section.</p>
<h3 id="heading-left-sidebar">Left Sidebar</h3>
<ul>
<li>Highlighted in a purple box in the previous diagram.</li>
<li>Shows you all the strings in your document and a preview of your source file.</li>
<li>You will find helpful tools at the top such as (from left to right): searching strings in the file, changing the view to a list of all the strings, highlighting translated and untranslated strings, showing the translation preview, scale toggle, and adding a string.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/toolbar-options.png" alt="Image" width="600" height="400" loading="lazy">
<em>Left Sidebar - Toolbar at the top.</em></p>
<p>If you click on the first button (from left to right) after the search file field, you can change the view to see a list of all the strings instead of the file preview. </p>
<p>Now you will see a list of all the strings on the left:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/list-of-all-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Basic list view.</em></p>
<p>You can always click on this button again to go back to the previous mode, where you can see the strings in the original context and layout of the source file, like this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>WYSIWYG ("What You See Is What You Get") Translation Mode.</em></p>
<p>Here, you will see that strings are highlighted in different colors. </p>
<ul>
<li>Red means that the string has not been translated.</li>
<li>Yellow means that the string is partially translated.</li>
<li>Blue means that the string has been translated.</li>
<li>Gray means that the string is hidden and only visible to project managers and proofreaders.</li>
</ul>
<p>When you start proofreading the strings, you will also see:</p>
<ul>
<li>A yellow checkmark if the string is partially approved (if some plural forms are not approved).</li>
<li>A green checkmark if the string has been approved.</li>
</ul>
<p>You may also see a comment icon if a contributor has left a comment on a string or if it has marked the comment as an issue.</p>
<h3 id="heading-middle-top-area">Middle-Top Area</h3>
<ul>
<li>Highlighted in a yellow box in the diagram below. </li>
<li>This is where you can translate a string. You just need to select it from the left sidebar and it will appear in this area. </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor-sections.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor in Comfortable Mode.</em></p>
<p>Let's click on a string and see what happens:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/selecting-a-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting a string.</em></p>
<p>Awesome! The string is now selected as the "Source String" and we can start translating it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/writing-translations.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translate a string.</em></p>
<p>The three tools that you can see at the bottom are (from left to right):</p>
<ul>
<li><strong>Copy Source:</strong> to keep the initial string structure. </li>
<li><strong>Clear:</strong> to erase the translation quickly.</li>
<li><strong>Text Selection Mode:</strong> to copy a part of the translation from Translation Memory (TM) or Machine Translations (MT).</li>
</ul>
<p>If you click on the three dots at the top, you will see additional options for the string, including:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/strings-translation-options.png" alt="Image" width="600" height="400" loading="lazy">
<em>String translation options.</em></p>
<ul>
<li>Hide String.</li>
<li>Copy String URL.</li>
<li>Copy Source Skeleton.</li>
<li>Translation History.</li>
<li>View String in Context.</li>
</ul>
<p>When you write your translation, you will see your translations in the preview. The string will be highlighted in yellow if it is the selected string. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/preview-with-partially-translated-string.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation in the preview (sidebar). The translated string is in Spanish in the preview.</em></p>
<p>To save your translation, click on the green "Save" button. </p>
<p>After this, you can go to the next string and you will see the previously translated string highlighted in a different color (blue).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translated-saved-string.png" alt="Image" width="600" height="400" loading="lazy">
<em>Saved translation.</em></p>
<p>To go back to the previous string, just click on it or click on the left arrow next to "Source String".</p>
<p>If you go back to the string, you will see something new in the middle-bottom area.</p>
<p>Let's talk about the middle-bottom area.</p>
<h3 id="heading-middle-bottom-area">Middle-Bottom Area</h3>
<ul>
<li>Highlighted in an orange box in the diagram below.</li>
<li>This section has translations made by other contributors (if applicable), translation memory (TM) suggestions, machine translation (MT) suggestions, and translations to other languages.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor-sections.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor in Comfortable Mode.</em></p>
<p><strong>💡 Tip:</strong> If you click on a suggestion, it will automatically appear in the translation input field.</p>
<p>This is the current state of our project. We have this translated string and you can see the Spanish Translation in the middle-bottom section (orange box below).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/back-to-translated-string.png" alt="Image" width="600" height="400" loading="lazy">
<em>Middle-Bottom Section.</em></p>
<p>For each translation, you will see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/approve-string-translation.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation.</em></p>
<ul>
<li>The translation in the target language.</li>
<li>The Crowdin user who saved the translation. </li>
<li>When it was saved.</li>
<li>Its current rating (other project members can upvote or downvote a translation).</li>
<li>A checkmark button to approve the translation (like a proofreader).</li>
<li>A trash button to delete the translation.</li>
</ul>
<p>If you are the project owner or you have proofreading permissions, you can approve the string translation yourself. However, it is always recommended to have another team member check your string to avoid any common issues.</p>
<p>To approve the translation, just click on the checkmark button next to the translation. </p>
<p>Now you will see the approved string highlighted in green in the preview:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/approved-string.png" alt="Image" width="600" height="400" loading="lazy">
<em>Approved string highlighted in green.</em></p>
<p>The translated string will now show who approved it and when it was approved:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/back-to-approved-string-1.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-right-sidebar">Right Sidebar</h3>
<p>And last (but not least!) we have the right sidebar. </p>
<ul>
<li>Highlighted in blue in the diagram below.</li>
<li>This is where you can write comments, search the TM, search for terms on your glossary, add new apps, and find the apps you added through the <a target="_blank" href="https://crowdin.com/store/apps">Crowdin Store</a>.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-editor-sections.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor in Comfortable Mode.</em></p>
<p>To write a comment, just go to the comments on the sidebar and write your comment on the text input field at the bottom. You can mark the comment as an issue if you need to.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/writing-a-comment-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Writing a comment.</em></p>
<p>💡 <strong>Tip:</strong> You should write your comment using the source language of the project, so other team members and project managers can understand it.</p>
<p>If you click on the second option on this sidebar, you will be able to search your translation memory for previous translations.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-memory.png" alt="Image" width="600" height="400" loading="lazy">
<em>Search Translation Memory (TM).</em></p>
<p>In the third option, you can search for terms related to the currently selected string in your glossary.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Search Terms.</em></p>
<p>What is really great about this search term feature is that, <a target="_blank" href="https://support.crowdin.com/online-editor/#section-4">according to Crowdin</a>:</p>
<blockquote>
<p>If the specific term is not available in the project’s glossary, the system will show you Wikipedia explanations.</p>
</blockquote>
<p>This can be very helpful to understand more about the context of a term when you are translating a resource.</p>
<p>And the last option is a plus icon that will take you to the Crowdin Store, where you can find apps and integrations for your project and you will be able to access them on the sidebar.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/add-apps.png" alt="Image" width="600" height="400" loading="lazy">
<em>Go to the Crowdin Store.</em></p>
<h2 id="heading-translation-editor-modes">Translation Editor Modes</h2>
<p>The translation editor has three modes to customize the layout in a way that fits your needs — Comfortable Mode, Side-by-Side Mode, and Multilingual Mode.</p>
<h3 id="heading-comfortable-mode">Comfortable Mode</h3>
<ul>
<li>Primarily used for translations. </li>
<li>It has the four main sections that we saw in the previous section.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/comfortable-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>Layout in the Comfortable Mode.</em></p>
<h3 id="heading-how-to-switch-modes">How to Switch Modes</h3>
<p>To switch to another mode, you need to click on the menu icon at the top left of the translation editor:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/change-mode-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click on this menu icon.</em></p>
<p>Then, click on "View" and choose the mode that you would like to see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/view-change-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>Change Editor View.</em></p>
<h3 id="heading-side-by-side-mode">Side-by-Side Mode</h3>
<ul>
<li>Primarily used by managers and proofreaders to approve the best translations and by translators to vote translations in a row.</li>
</ul>
<p>The first time you switch to this view, you will see some helpful tips:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tip-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Review or make translations.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tip-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Approve multiple translations at once.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tip-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Switch to Comfortable view to make new translations.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tip-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>That's all friends!</em></p>
<p>This is what you will see when you enter side-by-side mode. Please take a moment to see it in detail and explore the changes:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/side-by-side-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>Side-by-Side Mode</em></p>
<p>To see all the possible string status in the side-by-side mode, let's go back to the Comfortable Mode to translate and save another string (but we will not approve the string this time).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/string-translation-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translating another string.</em></p>
<p>In the side-by-side view, we now have a translated string, an approved string, and strings that we still need to translate.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/side-by-side-with-multiple-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Side-by-Side Mode.</em></p>
<p>Let's start with a quick tour. You have four areas that you can resize to fit your needs:</p>
<ul>
<li>At the top left, we find the list of strings. You can select multiple string for bulk operations such as approving multiple strings with just one click.</li>
<li>At the bottom left, we find the preview of the source file. </li>
<li>At the top right, we find the string details.</li>
<li>At the bottom right, we find the current translations and suggestions. This is very similar to what you see in the Comfortable mode.</li>
</ul>
<h4 id="heading-toolbar">Toolbar</h4>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/toolbar.png" alt="Image" width="600" height="400" loading="lazy">
<em>Toolbar.</em></p>
<p>At the top of the list of string, you will see multiple tools, including (from left to right):</p>
<ul>
<li>Search for a string.</li>
<li>Change sorting criteria.</li>
<li>String length in the source file and in the translated version. </li>
<li>Save button. </li>
<li>Cancel button. </li>
<li>Copy source.</li>
<li>Approve string.</li>
<li>Add string.</li>
<li>Edit string.</li>
<li>More options.</li>
</ul>
<p>If you open the "More options" menu by clicking on the three dots, you will see more helpful options for the selected string(s).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/more-options-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>More options.</em></p>
<h4 id="heading-how-to-sort-the-strings">How to Sort the Strings</h4>
<p>You will notice that, by default, the strings will be sorted by their status. </p>
<p><strong>💡 Tip:</strong> Untranslated strings will be displayed first, so you will not see the strings in the order in which they appear in the source file. </p>
<p>You can change the sorting criteria by clicking on the filter icon next to the search field. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/filtering-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Filtering the Strings.</em></p>
<p>In this mode, you will also see different visual references of the status of each string. </p>
<p>Here, we can see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/types-of-strings.png" alt="Image" width="600" height="400" loading="lazy">
<em>String status.</em></p>
<ul>
<li>An untranslated string in red.</li>
<li>A translated string in blue. </li>
<li>An approved string with a green checkmark. </li>
<li>A hidden string in gray. </li>
</ul>
<h3 id="heading-multilingual-mode">Multilingual Mode</h3>
<p>Awesome. Now let's go to the multilingual mode. This mode is primarily used by translators and proofreaders to work with multiple languages at the same time.</p>
<p>💡 <strong>Tip:</strong> You can work on up to ten languages simultaneously.</p>
<p>To switch to this mode, click on the main menu icon at the top. Then select "View" and choose "Multilingual".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/multilingual-view.png" alt="Image" width="600" height="400" loading="lazy">
<em>Go to the Multilingual Mode.</em></p>
<p>When you choose "Multilingual", you will need to choose the languages that you are planning to work with.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/languages.png" alt="Image" width="600" height="400" loading="lazy">
<em>Languages for the Multilingual Mode.</em></p>
<p>Let's choose Spanish and Japanese just to see how this mode works. Click on them and then click on the "Apply" button.</p>
<p>You should see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/multilingual-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>Multilingual Mode.</em></p>
<p>Each string will have a text field where you can write the translation for each of the target languages selected. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/string-in-multilingual.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>When you are working on the multilingual mode, you can switch between two possible views:</p>
<ul>
<li>List View.</li>
<li>Grid View.</li>
</ul>
<p>This is an example of the list view:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/multilingual-mode.png" alt="Image" width="600" height="400" loading="lazy">
<em>List view in Multilingual Mode.</em></p>
<p>To switch to Grid View, you need to click on the button in the toolbar at the top:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/multilingual-mode-copy.png" alt="Image" width="600" height="400" loading="lazy">
<em>Switch between list and grid view.</em></p>
<p>The other parts of the editor and the tools in this mode are very similar to the Side-by-Side view that you are already familiar with.</p>
<h2 id="heading-how-to-switch-to-another-file">How to Switch to Another File</h2>
<p>You may want to go to another file after translating all the strings in a different file. This is very easy to do.</p>
<p>To do that:</p>
<p>Click on the main menu at the top left.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/main-menu-button.png" alt="Image" width="600" height="400" loading="lazy">
<em>Main Menu.</em></p>
<p>Go to File and then choose "Open...".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/open-another-file-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Open a File.</em></p>
<p>Choose the file that you would like to open and click on "Open" (or double-click on the file name).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/open-file-menu.png" alt="Image" width="600" height="400" loading="lazy">
<em>List of files.</em></p>
<p>💡 <strong>Tip:</strong> You can also get to the list of files much faster by clicking on the file name directly. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/file-click-on-file.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click on the file name.</em></p>
<p>You will be taken to the file you've chosen.</p>
<h3 id="heading-how-to-view-all-strings">How to View All Strings</h3>
<p>If you ever need to see a list of all the strings in a project, you just need to:</p>
<p>Go to the main menu at the top left.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/main-menu-button.png" alt="Image" width="600" height="400" loading="lazy">
<em>Main Menu.</em></p>
<p>Go to "File", and then select "All Strings".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/all-strings-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>See All Strings.</em></p>
<p>You will see a list of all the strings in the project, their status, and translations. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/all-strings-list.png" alt="Image" width="600" height="400" loading="lazy">
<em>All Strings.</em></p>
<h2 id="heading-how-to-translate-rtl-languages">How to Translate RTL Languages</h2>
<p>While some languages like Spanish and Italian are written from left to right (LTR), other languages like Arabic and Urdu are written from right to left (RTL). </p>
<p><a target="_blank" href="https://support.crowdin.com/online-editor/#translating-rtl-languages">Crowdin mentions</a> that:</p>
<blockquote>
<p>When translating between LTR and RTL languages, some elements in the translation field in the Editor might not be displayed the same way as they will be once exported.</p>
</blockquote>
<p>To make sure that the translations will be displayed correctly in the exported file, Crowdin recommends:</p>
<ol>
<li>Clicking the "Copy Source" button when writing the translations. This is the first button on the toolbar.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/toolbar-copy-source-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The "Copy Source" Button.</em></p>
<ol start="2">
<li><p>Translating the text into your target language.</p>
</li>
<li><p>Leaving any variables or tags exactly the same, even if they do not look the same. They will be in the right position when you export a file.</p>
</li>
</ol>
<p>💡 <strong>Tip:</strong> Crowdin <a target="_blank" href="https://support.crowdin.com/online-editor/#translating-rtl-languages">suggests</a> using the <a target="_blank" href="https://store.crowdin.com/unicode">Unicode Table app</a> to copy and paste right-to-left and left-to-right marks, changing the direction of the text where needed.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-77.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of translating a RTL language from the <a target="_blank" href="https://support.crowdin.com/online-editor/#translating-rtl-languages">Crowdin documentation</a>.</em></p>
<h3 id="heading-translation-editor-settings">Translation Editor Settings</h3>
<p>You can also customize the settings of the translation editor. </p>
<p>To access these settings, click on the gear icon at the top right of the translation editor.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/editor-settings.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation Editor Settings.</em></p>
<p>You will see a list of the settings that you can customize.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/editor-settings-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Editor Settings (Part 1)</em></p>
<p>The first part of these settings includes:</p>
<ul>
<li>The minimum match percentage for showing Translation Memory suggestions. </li>
<li>If translations should be checked for quality assurance (QA) issues.</li>
<li>If the editor should auto-complete what you are writing and show you a list of predictions. </li>
<li>If you would like to approve the translations automatically. This can be helpful if you are translating and proofreading the project yourself.</li>
<li>If you would like to move to the next string automatically. </li>
<li>The color theme for the translation editor (light, dark, or automatic).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/editor-settings-2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Editor Settings (Part 2).</em></p>
<p>If you scroll down, you will find more settings, such as:</p>
<ul>
<li>If the editor should show only the beginning of the source string in a compact view.</li>
<li>If you would like to show the translation preview for translated strings.</li>
<li>How HTML tags should be displayed. You can show them or hide them. </li>
<li>If non-printable characters should be displayed or not. </li>
<li>If the translation field should be highlighted.</li>
<li>If you would like to enable real-time spellchecking.</li>
<li>The language of the user interface of your translation editor.</li>
</ul>
<p>You can customize these settings to fit your needs.</p>
<h3 id="heading-keyboard-shortcuts">Keyboard Shortcuts</h3>
<p>Another key productivity feature for translators and proofreaders on Crowdin is that they can use keyboard shortcuts.</p>
<p>To see all the keyboard shortcuts available for your operating system, just click on the keyboard icon at the top right.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/keyboard-shortcuts-button-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Open Keyboard Shortcuts.</em></p>
<p>These are the keyboard shortcuts for Windows:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-78.png" alt="Image" width="600" height="400" loading="lazy">
<em>Keyboard Shortcuts (Windows). Screenshot from the <a target="_blank" href="https://support.crowdin.com/online-editor/#helpful-tips">Crowdin Documentation</a>.</em></p>
<p>And these are the keyboard shortcuts for macOS:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/keyboard-shortcuts-macos-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Keyboard Shortcuts (macOS).</em></p>
<p>If you scroll down, you will find more keyboard shortcuts for macOS.</p>
<h2 id="heading-how-to-download-the-translated-files">How to Download the Translated File(s)</h2>
<p>Once your project is translated and approved, you will need to download it. </p>
<p>In Crowdin, you have three different options for downloading files. You can download the entire project, download all the project files in a specific language, or download a specific file in a specific language.</p>
<p>Let's see these options in more detail. </p>
<h3 id="heading-how-to-download-the-entire-project">How to Download the Entire Project</h3>
<p>If you need to download the entire project:</p>
<ol>
<li>Go to your project.</li>
<li>Go to the "Translations" tab. </li>
<li>On "Download as ZIP" section, click on the "Build &amp; Download" button.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-project-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download as ZIP.</em></p>
<p>You will see a progress bar while Crowdin builds the project and then your download will start.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/progress-bar.png" alt="Image" width="600" height="400" loading="lazy">
<em>Build &amp; Download.</em></p>
<p>The ZIP file will have folders for each language. The names of the folders will be their corresponding language codes.</p>
<h3 id="heading-how-to-download-all-files-in-a-target-language">How to Download All Files in a Target Language</h3>
<p>This option is helpful if you need to download all the translated files in a specific target language.</p>
<ol>
<li>Go to your project. </li>
<li>Go to the "Translations" tab.</li>
<li>On "Download as ZIP" section, select the language.</li>
<li>Click on the "Build &amp; Download" button.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-language-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download as ZIP.</em></p>
<h3 id="heading-how-to-download-a-file-in-a-target-language">How to Download a File in a Target Language</h3>
<p>The third option is to download just one file in a specific target language. </p>
<p>To do this:</p>
<ol>
<li>Go to your project.</li>
<li>Go to the Dashboard tab.</li>
<li>Choose the target language. </li>
<li>Click on the file.</li>
<li>Click on the three dots to the right to see the additional options (see the screenshot below).</li>
<li>Click on "Download".</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-one-file.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download a File in a Target Language.</em></p>
<p>The download should start and you should have your translated file ready in just a few seconds or minutes.</p>
<p>You can also automate the process of exporting or downloading your translated files with Crowdin integrations. </p>
<h2 id="heading-how-to-use-translation-memory-tm"><strong>How to Use Translation Memory (TM)</strong></h2>
<p>Great work so far. Now that you know the basic features of the translation editor, let's talk about more advanced features such as the Translation Memory. </p>
<p>We will see how you can:</p>
<ul>
<li>Create translation memory.</li>
<li>Manage translation memory.</li>
<li>Download and upload translation memory.</li>
<li>Assign translation memory to a project.</li>
</ul>
<p>💡 <strong>Tip:</strong> Remember that TM is like a database of strings that we have translated previously in our project and their corresponding translations. Reusing previous translations can save us a lot of time. </p>
<p>Are you ready? Let's begin. </p>
<h3 id="heading-how-to-create-a-translation-memory-tm">How to Create a Translation Memory (TM)</h3>
<p>To create a TM for your project, you need to:</p>
<ol>
<li>Go to your profile. You can do this by clicking on "Profile" in the dropdown menu that is displayed when you click on your profile image at the top right.</li>
<li>Go to the "Resources" tab.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/resources-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Resource tab in Profile.</em></p>
<ol start="3">
<li>If you already have a project created, you will see a TM for that project. You can also create a new TM, independently from a project (you can assign it to a project later on).</li>
</ol>
<p><a target="_blank" href="https://support.crowdin.com/translation-memory/#creating-tm">Crowdin mentions</a> that:</p>
<blockquote>
<p>Besides the project TMs that are automatically created along the respective projects, you can also create separate TMs, fill them with the appropriate content by uploading your existing TMs in TMX, XLSX, or CSV format, and then assign these TMs to the needed projects.</p>
</blockquote>
<ol start="4">
<li>To create a new TM, click on the green "Create TM" button.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-TM-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create TM.</em></p>
<ol start="5">
<li>Complete the information for your new TM, such as its name, language, and if you would like to assign it to an existing project.</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-translation-memory.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create Translation Memory.</em></p>
<p>I'm going to create a new TM called "Demo TM" in English. For now, I will not assign it to any project.</p>
<p>Let's see what happens:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-translation-memory.png" alt="Image" width="600" height="400" loading="lazy">
<em>New TM.</em></p>
<p>🎉 Awesome. Now we see the new TM in the list.</p>
<h3 id="heading-how-to-manage-translation-memory-tm">How to Manage Translation Memory (TM)</h3>
<p>If you click on the three dots to the right of the TM to show additional options, you will see the following options:</p>
<ul>
<li>Upload.</li>
<li>Download.</li>
<li>Edit.</li>
<li>View Records.</li>
<li>Delete.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/additional-options-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Additional Options for a Translation Memory.</em></p>
<p>If you select a TM by checking its checkbox, you can delete it, edit it, or view its records. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/manage-tm-2.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>Since our new TM is new (and therefore, empty), let's see the records of the TM for our freeCodeCamp Course Project.</p>
<p>If you click on it, you'll see a list of all the records stored in the TM:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-memory-strings-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation Memory (TM).</em></p>
<p>From here, you can:</p>
<ul>
<li>Edit the records.</li>
<li>Delete the records.</li>
<li>Search for specific records matching case, whole phrase, and finding an exact match.</li>
<li>Hide or show specific columns.</li>
</ul>
<h3 id="heading-how-to-upload-and-download-translation-memory-tm">How to Upload and Download Translation Memory (TM)</h3>
<p>In the "Resources" tab of your project, you can also upload and download TM.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tm-records-download-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>Resources toolbar.</em></p>
<p>The file must be in one of the following formats: </p>
<ul>
<li>TMX</li>
<li>XLSX</li>
<li>CSV</li>
</ul>
<p>To upload a TM:</p>
<ul>
<li>Click on the "Upload" button. </li>
<li>Choose your file in your file system. </li>
<li>Match each column to the corresponding language.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tm-records-download-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>The "Upload" button.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-79.png" alt="Image" width="600" height="400" loading="lazy">
<em>Matching columns to their corresponding languages. Image taken from the <a target="_blank" href="https://support.crowdin.com/translation-memory/#downloading-and-uploading-tm">Crowdin Documentation</a>.</em></p>
<p>To download translation memory:</p>
<ul>
<li>Click on the "Download" button. </li>
<li>Select the file format (either TMX, XLSX, or CSV).</li>
<li>Choose if you would like to download all languages or only a specific language pair.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tm-records-download-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>The "Download" button.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-tm.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download TM.</em></p>
<p>The download should start after you click on the green "Download" button. </p>
<p>This is the CSV file that we get when we export the Translation Memory of our freeCodeCamp Course Project:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-19-at-5.19.49-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Exported CSV File.</em></p>
<h3 id="heading-how-to-assign-translation-memory-to-a-project">How to Assign Translation Memory to a Project</h3>
<p>To assign an existing TM to a project:</p>
<ol>
<li>Go to your project.</li>
<li>Go to the "Settings" tab.</li>
<li>Go to "Translation Memories".</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assign-tm.png" alt="Image" width="600" height="400" loading="lazy">
<em>Settings tab.</em></p>
<ol start="4">
<li>Scroll down to find "Assigned Translation Memories".</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assigned-tm.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ol start="5">
<li>Select the Translation Memories that you would like to assign to your project. </li>
</ol>
<p><a target="_blank" href="https://support.crowdin.com/translation-memory/#prioritizing-tm">Crowdin mentions</a> that:</p>
<blockquote>
<p>When you assign a few TMs to the project, you can set the needed priority for each of them. As a result, TM suggestions from the TM with the higher priority will be displayed in the first place.</p>
</blockquote>
<p>💡 <strong>Tip:</strong> A higher number represents a higher priority. If a TM has a priority of 5, that would be higher than a priority of 1.</p>
<p>You can also change the default TM by clicking on the corresponding star icon.</p>
<p><strong>Important:</strong> Please note that Crowdin recently eliminated the need to use custom workflows to automatically apply Translation Memory matches. Now you can enable Translation Memory on the project settings, like you can see below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image-13.png" alt="Image" width="600" height="400" loading="lazy">
<em>How to Enable Translation Memory Pre-Translation for New Content in the Project Settings. Screenshot provided by the Crowdin team.</em></p>
<h2 id="heading-glossary-1">Glossary</h2>
<p>Awesome! Now you know the most important aspects of TM on Crowdin, so let's check out the glossaries.</p>
<p>💡 <strong>Tip:</strong> Remember that a glossary allows you to store and manage your project's terminology to help your translators with more context and definitions.</p>
<h3 id="heading-how-to-create-a-glossary">How to Create a Glossary</h3>
<p>When you create a project, a glossary is automatically created but you can also create new ones that are independent from any project.</p>
<p>To create a glossary:</p>
<ul>
<li>Go to your profile.</li>
<li>Go to "Resources".</li>
<li>Click on "Glossaries".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossaries-tab.png" alt="Image" width="600" height="400" loading="lazy">
<em>Glossaries</em></p>
<p>You will see a glossary for each project that you have created on Crowdin. </p>
<ul>
<li>Click on the green "Create Glossary" button.</li>
<li>Choose a name and a language for your glossary. </li>
<li>If you need to, assign it to a project.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-a-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assign to a Glossary.</em></p>
<p>After this, you will see your new glossary in the list of glossaries. I created a new glossary called "Demo Glossary".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>List of Glossaries.</em></p>
<h3 id="heading-how-to-manage-glossary-terms">How to Manage Glossary Terms</h3>
<p>You can add, edit, and delete concepts and terms from your glossaries. Let's see how you can do this step by step.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/empty-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>New Empty Glossary.</em></p>
<p><strong>💡 Tip:</strong> On Crowdin, concepts is not the same as a term. A concept is broader than a term. This is what <a target="_blank" href="https://support.crowdin.com/glossary/#managing-glossary-concepts-and-terms">the documentation</a> says about their difference:</p>
<blockquote>
<p>A concept incorporates glossary terms and their variations with multiple translations and other relevant information.</p>
</blockquote>
<p>To add a concept, click on the green "Add concept" button:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/add-concept-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add concept.</em></p>
<p>You will need to write information about the new concept:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-19-at-6.08.32-PM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add concept dialog.</em></p>
<p>The <a target="_blank" href="https://support.crowdin.com/glossary/#managing-glossary-concepts-and-terms">Crowdin documentation</a> describes the following concept details:</p>
<blockquote>
<p><strong>Definition:</strong> concept definition.<br><strong>Subject:</strong> a branch of knowledge the concept is related to.<br><strong>Note:</strong> short notes about a concept that might be helpful to translators.<br><strong>URL:</strong> URL to the web page with relevant information about a concept.<br><strong>Figure:</strong> URL to the relevant image.</p>
</blockquote>
<p>It also mentions the following <strong>term</strong> details:</p>
<blockquote>
<p><strong>Part of speech:</strong> e.g., noun, verb, adjective, etc.<br><strong>Type:</strong> e.g., full form, acronym, abbreviation, etc.<br><strong>Status:</strong> preferred, admitted, not recommended, obsolete.<br><strong>Gender:</strong> term gender.<br><strong>Description:</strong> term description.<br><strong>Note:</strong> short notes about a term that might be helpful to translators.<br><strong>URL:</strong> URL to the web page with relevant information about a term.</p>
</blockquote>
<p>After you create the term, you will see it in the list of terms for the glossary:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossary-term-demo.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>To edit or delete a glossary term, click on the three dots to the right to see additional options and choose an option. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glosssary-term-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Glossary Term.</em></p>
<p>You can download or upload a glossary in the following formats: </p>
<ul>
<li>TBX (v2)</li>
<li>TBX (v3)</li>
<li>CSV</li>
<li>XLSX</li>
</ul>
<p>Just click on the corresponding button and you will be able to choose a file to upload or the format of the file to download.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload and Download a Glossary.</em></p>
<p><a target="_blank" href="https://support.crowdin.com/glossary/#downloading-and-uploading-glossary">Crowdin suggests</a> that:</p>
<blockquote>
<p>If you upload a glossary in CSV or XLS/XLSX file formats, select the language for each column and the column value (term, description, or part of speech) in the configuration dialog.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-80.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting the columns. Image taken from the <a target="_blank" href="https://support.crowdin.com/glossary/#downloading-and-uploading-glossary">Crowdin documentation</a>.</em></p>
<h3 id="heading-how-to-assign-a-glossary-to-a-project">How to Assign a Glossary to a Project</h3>
<p>It is very easy to assign a glossary to a project on Crowdin. </p>
<p>You just need to:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Settings" tab.</li>
<li>Go to "Glossaries".</li>
<li>Select the glossary (or glossaries) that you would like to assign to your project.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossaries-demo.png" alt="Image" width="600" height="400" loading="lazy">
<em>Project Glossaries.</em></p>
<p><strong>💡 Tip:</strong> To change the default glossary of a project, just click on the star icon of the corresponding glossary. The dark gray star marks the current default glossary.</p>
<p>You can also share glossaries across all your projects by checking the option "Share Glossaries" in your profile:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/share-glossaries.png" alt="Image" width="600" height="400" loading="lazy">
<em>Share Glossaries.</em></p>
<h3 id="heading-how-to-translate-the-glossary">How to Translate the Glossary</h3>
<p>Translating your glossary can be very helpful to use terms consistently in your target languages.</p>
<p>To translate your glossary, Crowdin recommends using the free <a target="_blank" href="https://crowdin.com/store/apps/glossary-translate-app">Translate Glossary</a> app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translate-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translate Glossary app.</em></p>
<p>If you install the app, you will be able to translate your glossary directly on Crowdin and choose which projects should have access to this app.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/install-translate-glossary.png" alt="Image" width="600" height="400" loading="lazy">
<em>Install the app.</em></p>
<h2 id="heading-quality-assurance-qa-checks-in-crowdin">Quality Assurance (QA) Checks in Crowdin</h2>
<p>Quality assurance is essential for every type of project and this is especially true for localization projects. One small typo or spelling mistake can make all the difference to your users. </p>
<p>This is why Crowdin implemented efficient quality assurance features to help you deliver the high-quality translations that your users deserve.</p>
<p>According to <a target="_blank" href="https://support.crowdin.com/qa-checks/">Crowdin</a>:</p>
<blockquote>
<p>QA checks help to detect some common mistakes easily and quickly. It’s recommended to review and resolve all QA check issues before building your project and downloading translations.</p>
</blockquote>
<p>The issues detected by the QA Checks include:</p>
<ul>
<li>Typos.</li>
<li>Missing commas.</li>
<li>Extra spaces.</li>
<li>Other common mistakes.</li>
</ul>
<h3 id="heading-how-to-configure-quality-assurance-qa-checks">How to Configure Quality Assurance (QA) Checks</h3>
<p>To configure QA checks and choose what you would like to check for in the translated strings, you just need to:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Settings" tab.</li>
<li>Make sure that "Enable QA Checks" is selected.</li>
<li>Select what you would like to check for.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-checks-settings.png" alt="Image" width="600" height="400" loading="lazy">
<em>The QA Checks category.</em></p>
<p>You can check:</p>
<ul>
<li>If a translation is empty.</li>
<li>If the translation is longer than the predefined length limit (if it exists).</li>
<li>Tags mismatch.</li>
<li>Spaces mismatch.</li>
<li>Variables mismatch.</li>
<li>Punctuation mismatch.</li>
<li>Character case mismatch.</li>
<li>Special characters mismatch.</li>
<li>"Incorrect translation" issues.</li>
<li>Spelling issues.</li>
<li>ICU Syntax errors.</li>
<li>Consistency with the glossary terms.</li>
<li>Duplicate translation.</li>
<li>FTL syntax errors.</li>
<li>Android syntax errors.</li>
</ul>
<p><strong>💡 Tip:</strong> For each of these QA checks, you can choose if you would like to show a warning to the user when the string is being saved or if you would like to go one step further and show an error.</p>
<p>To save your changes, click on the green "Save" button.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-save-button.png" alt="Image" width="600" height="400" loading="lazy">
<em>Save QA Checks.</em></p>
<h3 id="heading-how-to-check-quality-assurance-status">How to Check Quality Assurance Status</h3>
<p>Proofreaders and project managers can see the issues found by the quality assurance checks. </p>
<p>To see the current status, you just need to:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Dashboard" tab. </li>
<li>Find the "QA Checks" status. </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-checks-status-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>QA Checks with no issues.</em></p>
<p>You will see one of the following status:</p>
<ul>
<li><strong>Off</strong>: When the QA checks are not enabled.</li>
<li><strong>In Progress</strong>: When the QA checks are working.</li>
<li><strong>No Issues</strong>: When the QA checks did not find any issues.</li>
<li><strong>Issues Found</strong>: When the QA checks has found issues.</li>
</ul>
<p>If you try to save a string with QA check issue, you will see a warning or an error. You can save it anyway, but you should always try to fix these issues first. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/qa-warning.png" alt="Image" width="600" height="400" loading="lazy">
<em>A warning from adding extra spaces.</em></p>
<p>💡 <strong>Tip:</strong> Clicking the "Autofix" button on the warning will try to fix the issue automatically. You can also save it anyway or cancel.</p>
<p>This is a sample image from the Crowdin documentation showing what you should see if quality assurance issues are found in your project:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-81.png" alt="Image" width="600" height="400" loading="lazy">
<em>QA checks issues found. Image taken from the <a target="_blank" href="https://support.crowdin.com/qa-checks/">Crowdin documentation</a>.</em></p>
<p>Quality assurance is a very important step that you should definitely take very seriously during your localization process.</p>
<h2 id="heading-how-to-upload-existing-translations">How to Upload Existing Translations</h2>
<p>Great. If you have existing translations, you can also upload them to your project. </p>
<p>You have three options:</p>
<ul>
<li>Upload them via the Translations Tab. </li>
<li>Upload them via the Language Page.</li>
<li>Upload them via the Translation Editor.</li>
</ul>
<h3 id="heading-how-to-upload-via-the-translations-tab">How to Upload Via the Translations Tab</h3>
<p>To upload them via the Translations Tab:</p>
<ul>
<li>Go to your project.</li>
<li>Go to "Upload existing translations".</li>
<li>Drag and drop your existing translations or select the files from your file system. </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translations-tab-upload.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload translations via the Translations Tab.</em></p>
<p>According to Crowdin, the <a target="_blank" href="https://support.crowdin.com/uploading-translations/#key-value-formats">supported formats</a> for uploading translations include those that have a key-value structure, such as:</p>
<blockquote>
<p>Android XML, macOS/iOS Strings, Stringsdict, JSON, Chrome JSON, GO JSON, i18next JSON, FBT JSON, XLIFF, XLIFF 2.0, Java Properties, Play Properties, Java Properties XML, RESX, RESW, RES JSON, YAML, INI, Joomla INI, JS, FJS, PO, TS, QT TS, Blackberry, Symbian, Flex, BADA, TOML, Coffee, DKLANG, XAML, SRT, VTT, VTT2, SBV, SVG, DTD, CSV, RC, WXL, Maxthon, Haml, XLSX, PLIST, PHP, ARB, VDF.</p>
</blockquote>
<p>Crowdin also <a target="_blank" href="https://support.crowdin.com/uploading-translations/#text-and-html-based-formats">mentions</a> that:</p>
<blockquote>
<p>For files that do not have a defined structure, translation upload is handled by an experimental machine learning technology.  </p>
<p>This includes the following file formats: HTML, Front Matter HTML, Markdown, Front Matter Markdown, TXT, Generic XML, Web XML, DOCX, HAML, IDML, DITA, Wiki, FLSNP, MIF, and ADOC.</p>
</blockquote>
<h3 id="heading-how-to-upload-via-the-language-page">How to Upload Via the Language Page</h3>
<p>To upload them via the language page:</p>
<ul>
<li>Go to your project.</li>
<li>Go to "Dashboard".</li>
<li>Choose a target language.</li>
<li>Choose a file but instead of clicking on it, click on the three dots to its right to show more options. </li>
<li>Click on "Upload Translations".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-translations-language-page-2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload translations from the language page.</em></p>
<p>When you click on this option, you will see some settings for the upload and for assigning the translations. Check the options that you need for your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-options.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-upload-via-the-translation-editor">How to Upload Via the Translation Editor</h3>
<p>Finally, you can also upload translations directly from the translation editor.</p>
<p>To do this:</p>
<ul>
<li>Click on the main menu. </li>
<li>In File, select "Upload Translations..."</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/upload-from-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>Upload Translations from the Translation Editor.</em></p>
<h3 id="heading-supported-file-formats-on-crowdin">Supported File Formats on Crowdin</h3>
<p>So far, we have mentioned different file formats that you can work with on Crowdin. But Crowdin supports more than 100+ file formats. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/100-file-formats.png" alt="Image" width="600" height="400" loading="lazy">
<em>Supports more than 100+ file formats.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/supported-file-formats.png" alt="Image" width="600" height="400" loading="lazy">
<em>Supported file formats in the Crowdin Store.</em></p>
<p>You can check the supported file formats in the following resources:</p>
<ul>
<li><a target="_blank" href="https://support.crowdin.com/supported-formats/">Supported Formats</a>.</li>
<li><a target="_blank" href="https://store.crowdin.com/categories/file-formats">File Formats in the Crowdin Store</a>.</li>
</ul>
<h2 id="heading-how-to-pre-translate-your-project">How to Pre-Translate your Project</h2>
<p>If your goal is to save time and improve your productivity, pre-translation through Machine Translation (MT) can be exactly what you need. </p>
<p>This is an automated process that applies computer-generated translations to your project when you upload a file. On Crowdin, you can configure machine translation engines to use this feature.</p>
<p>You have two alternatives to implement this process:</p>
<ul>
<li>Manual.</li>
<li>Automated.</li>
</ul>
<h3 id="heading-manual-pre-translation">Manual Pre-Translation</h3>
<p>To pre-translate your content manually via Machine Translation (MT):</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Dashboard" tab.</li>
<li>Click "Pre-translation".</li>
<li>Select via TM (Translation Memory) or via MT (Machine Translation).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/pretranslation-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pre-translation.</em></p>
<p>If you choose "via MT" (Machine Translation), you will have to choose your translation engine, target languages, and the files that you would like to pre-translate. You can also add labels.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-engine.png" alt="Image" width="600" height="400" loading="lazy">
<em>Pre-translate your project via MT.</em></p>
<h3 id="heading-automated-pre-translation">Automated Pre-Translation</h3>
<p>If you choose to automate the process, the system will pre-translate your new content automatically.</p>
<p>Recently, Crowdin added the possibility to enable Machine Translation Pre-Translation for new content in the project settings. If you enable this and you upload new content to your project, the system will translate automatically.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2024/01/image--1-.png" alt="Image" width="600" height="400" loading="lazy">
<em>Enable Machine Translation Pre-translate for new content. Screenshot provided by the Crowdin team.</em></p>
<h2 id="heading-offline-translation">Offline Translation</h2>
<p>Sometimes, you may need to work offline. Crowdin also has a great feature for this in situations where you or your team members would like to work on the translations offline.</p>
<p>To enable or disable this feature:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Settings" tab.</li>
<li>Go to "Privacy and Collaboration".</li>
<li>Check (or uncheck) the "Allow offline translation" option.</li>
</ul>
<p><strong>💡Tip:</strong> This feature can be enabled or disabled by project managers.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/settings-tab-offline-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Allow offline translation.</em></p>
<p>Each file can be downloaded via the Editor or via the Language page.</p>
<h3 id="heading-how-to-download-a-file-via-the-editor">How to Download a File via the Editor</h3>
<p>To download a file via the Translation Editor:</p>
<ul>
<li>Click on the main menu at the top left.</li>
<li>Go to File</li>
<li>Click on "Download" or "Export in XLIFF".  </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-files.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download file via the editor.</em></p>
<h3 id="heading-how-to-download-a-file-via-the-language-page">How to Download a File Via the Language Page</h3>
<p>To download a file via the language page:</p>
<ul>
<li>Go to your project.</li>
<li>Go to "Dashboard".</li>
<li>Select a language.</li>
<li>In the list of files, click on the three dots next to the file that you would like to download to show more options.</li>
<li>Select "Download" or "Export in XLIFF".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/language-download-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download file via the language page.</em></p>
<h3 id="heading-how-to-download-all-files-for-a-target-language">How to Download All Files for a Target Language</h3>
<p>If you need to download all the files for a target language:</p>
<ul>
<li>Go to your project.</li>
<li>Go to "Dashboard".</li>
<li>Select a language.</li>
<li>Click on the up and down arrow icon (see the screenshot below). </li>
<li>Select "Download translations" or "Export in XLIFF".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/download-files-from-language-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Download all translations.</em></p>
<h2 id="heading-exploring-public-projects">Exploring Public Projects</h2>
<p>Now that you know some of the most important features of Crowdin, you may also be asking yourself how you can explore other projects that are currently being translated on Crowdin. </p>
<p>If you click on "Projects" at the top and then you select "Explore Public Projects", you will see a page where you can explore public projects per topic and find popular projects on Crowdin.</p>
<p>You can also filter projects by searching on the search bar. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/explore-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>Explore Crowdin.</em></p>
<p>🎉 Congratulations. We just reached the end of the second part of the book, which was focused on Crowdin fundamentals. </p>
<p>Now we will dive into how teams and organizations can use Crowdin to manage their projects effectively. </p>
<h2 id="heading-crowdin-for-teams-and-organizations">🔹 <strong>Crowdin for Teams and Organizations</strong></h2>
<p>Awesome! Now let's see how Crowdin can help you if you are working with a team on a localization project or if you are the founder or manager of an organization that is interested in localizing a product or platform. </p>
<p>We will talk about how you can invite members, assign roles and tasks, and generate reports.</p>
<h3 id="heading-how-to-invite-project-members-and-contributors">How to Invite Project Members and Contributors</h3>
<p>To invite members to your project:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Members" tab.</li>
<li>Click on the green "Invite" button.</li>
</ul>
<p>💡 <strong>Tip:</strong> You can also click on the gray "Invite People" button at the top left to reach the same options.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/members-tab-2-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Members tab.</em></p>
<p>You will need to enter information for these options before sending the invitation(s):</p>
<ul>
<li>Role.</li>
<li>Email or Crowdin username.</li>
<li>Message.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-members.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sending an invitation.</em></p>
<p>If you click on "Select role", you should see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-role.png" alt="Image" width="600" height="400" loading="lazy">
<em>Selecting a role.</em></p>
<p>By default, the "Translator" role will be selected.</p>
<p>You will also see three fields where you can choose which languages you would like to assign that role. For example, a contributor could be a translator for Japanese and a translator and proofreader for Spanish.</p>
<p><strong>💡 Tip:</strong> If you leave it blank, the role will apply to all languages but you can also choose specific languages. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-role-copy.png" alt="Image" width="600" height="400" loading="lazy">
<em>Choosing specific languages.</em></p>
<p>We will talk more about member roles in just a moment. </p>
<p>💡 <strong>Tip:</strong> You can also change the role(s) of a member in the Profile section.</p>
<p>Once you are ready, click "Save" and you will go back to the main options. Click "Done" when you are ready to send the invitations.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-members.png" alt="Image" width="600" height="400" loading="lazy">
<em>Sending an invitation.</em></p>
<h3 id="heading-how-to-send-invitation-links">How to Send Invitation Links</h3>
<p>If you would like to invite your team members through a link instead of sending them a direct invitation, you can do so too. </p>
<p>Just click on the "Get Link" button at the bottom to copy the link and send it to the person that you would like to invite to your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-members-link.png" alt="Image" width="600" height="400" loading="lazy">
<em>Get an invitation link.</em></p>
<p>You will see a confirmation message at the top.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/link-copied-to-clipboard.png" alt="Image" width="600" height="400" loading="lazy">
<em>Confirmation Message.</em></p>
<p>Then, you can paste the link wherever you need to, like an email.</p>
<h3 id="heading-how-to-manage-invitation-links">How to Manage Invitation Links</h3>
<p>To manage your invitation links, click on the "Manage Links" option:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/manage-links.png" alt="Image" width="600" height="400" loading="lazy">
<em>Manage Links.</em></p>
<p>You will see a list of all the invitation links you have generated, when you generated them, and the role(s) you granted to the invitee.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invitation-links.png" alt="Image" width="600" height="400" loading="lazy">
<em>Invitation Links that have been generated.</em></p>
<p><strong>💡 Tip:</strong> You can copy them again by clicking on the link icon to their right or revoke them by clicking on "Revoke link".</p>
<p>If you click on "Done", you will go back to the previous screen and you can click the "X" button at the top to close it.</p>
<h2 id="heading-project-roles">Project Roles</h2>
<p>Now let's talk about the different roles that you can assign to your team members. Let's read the role descriptions provided by Crowdin in the <a target="_blank" href="https://support.crowdin.com/modifying-project-participants-roles/">documentation</a>:</p>
<h3 id="heading-owner">Owner</h3>
<blockquote>
<p>A person who created a project and has complete control over it. The owner can invite and manage project members, create projects, upload source and translation files to the project, set up integrations, etc.</p>
</blockquote>
<h3 id="heading-manager">Manager</h3>
<blockquote>
<p>Has similar rights as a project owner except the ability to manage some of the owner’s Resources (e.g., configuring MT engines, custom workflows, etc.) and delete projects.</p>
</blockquote>
<h3 id="heading-language-coordinator">Language Coordinator</h3>
<blockquote>
<p>Can manage certain features of a project only within languages they have access to.   </p>
<p>Language coordinators can translate and approve strings, manage project members and join requests, generate project reports, create tasks, and pre-translate the project content.   </p>
<p>Unlike managers, they do not have access to other project settings (e.g., project files, integrations, etc.).</p>
</blockquote>
<h3 id="heading-developer">Developer</h3>
<blockquote>
<p>Can upload files, edit translatable text, connect integrations, and use the API. Cannot manage project tasks, members and reports.</p>
</blockquote>
<h3 id="heading-proofreader">Proofreader</h3>
<blockquote>
<p>Can translate and approve strings. Doesn’t have access to project settings.</p>
</blockquote>
<h3 id="heading-translator">Translator</h3>
<blockquote>
<p>Can translate strings and vote for translations added by other members.</p>
</blockquote>
<h3 id="heading-blocked">Blocked</h3>
<blockquote>
<p>Doesn’t have access to the project.</p>
</blockquote>
<h3 id="heading-how-to-assign-or-change-roles">How to Assign or Change Roles</h3>
<p>You have two options to assign or change the role of a project member. </p>
<p>You can either:</p>
<ul>
<li>Set the role in the invitation.</li>
<li>Set the role on the member's profile page.</li>
</ul>
<h4 id="heading-how-to-set-the-role-in-the-invitation">How to Set the Role in the Invitation</h4>
<p>You can choose the role when you send an invitation to a new member.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-role.png" alt="Image" width="600" height="400" loading="lazy">
<em>Setting the role in the invitation.</em></p>
<h4 id="heading-how-to-setting-the-role-in-the-profile-page">How to Setting the Role in the Profile Page</h4>
<p>You can also go to the "Permissions" tab on the member's profile page to choose the roles that you would like to assign to that member and to choose the languages you would like to assign to them.</p>
<p>This is an example from the Crowdin <a target="_blank" href="https://support.crowdin.com/modifying-project-participants-roles/#languages-permissions">documentation</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-82.png" alt="Image" width="600" height="400" loading="lazy">
<em>Setting roles in the "Permissions" tab. Image taken from the Crowdin <a target="_blank" href="https://support.crowdin.com/modifying-project-participants-roles/#languages-permissions">documentation</a>.</em></p>
<p>Click on the "Save" button to save your changes.</p>
<h2 id="heading-project-managers">Project Managers</h2>
<p>Project managers play a key role for your team and for your project. They can have unlimited control over the entire project and they can help you coordinate and assign tasks to team members.</p>
<h3 id="heading-how-to-add-a-project-manager">How to Add a Project Manager</h3>
<p>Let's see how you can add a project manager to your project. You can assign the Manager role to a member when you send them an invitation:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Members" tab. </li>
<li>Click on "Invite".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-button-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>Members tab.</em></p>
<p>Click on "Translator". You will see all the possible roles. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-role-manager-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select a role.</em></p>
<p>Choose "Manager". This will grant the member unlimited control over the entire project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/manager-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Manager role.</em></p>
<p>Alternatively, you can invite a Manager from your profile page:</p>
<ul>
<li>Go to your profile.</li>
<li>Go to the "Managers" tab.</li>
<li>Click on "Add Manager".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/managers-tab-profile-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add Manager.</em></p>
<p>Now you will need to enter the name or username of the manager, the message, the permissions that you would like to grant, and the projects that will be managed by this manager.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/invite-manager-from-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>Invite Manager.</em></p>
<h3 id="heading-editing-manager-permissions">Editing Manager Permissions</h3>
<p>You can also edit manager permissions on Crowdin. </p>
<p>To do this:</p>
<ol>
<li>Go to your profile.</li>
<li>Go to the "Managers" tab. You will see a list of the managers that you've added to your projects.</li>
<li>Double-click on the manager you would like to edit.</li>
</ol>
<p>This is an example from the <a target="_blank" href="https://support.crowdin.com/manager-permissions/#editing-manager-permissions">Crowdin documentation</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-83.png" alt="Image" width="600" height="400" loading="lazy">
<em>Managers tab example. Image taken from the <a target="_blank" href="https://support.crowdin.com/manager-permissions/#editing-manager-permissions">Crowdin documentation</a>.</em></p>
<ol start="4">
<li><p>Update the permissions for that manager.</p>
</li>
<li><p>Click on the "Save" button.</p>
</li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/edit-permissions.png" alt="Image" width="600" height="400" loading="lazy">
<em>Imagen taken from the <a target="_blank" href="https://support.crowdin.com/manager-permissions/#editing-manager-permissions">Crowdin documentation</a>.</em></p>
<h3 id="heading-how-to-remove-a-manager">How to Remove a Manager</h3>
<p>To remove a manager:</p>
<ul>
<li>Go to your profile. </li>
<li>Go to the "Managers" tab.</li>
<li>Select the manager that you would like to remove.</li>
<li>Click "Remove".</li>
</ul>
<h3 id="heading-manager-vs-proofreader">Manager vs Proofreader</h3>
<p>On Crowdin, Managers and proofreaders have certain differences in their roles and permissions.</p>
<p>To explain this in more detail, the Crowdin team highlights this important question in the <a target="_blank" href="https://support.crowdin.com/modifying-project-participants-roles/#qa">documentation</a>:</p>
<blockquote>
<p>Q: <em>I’m a project owner. Do I need to invite a manager or a proofreader?</em>  </p>
<p>A: The main difference between a manager and a proofreader is the following: in addition to approving translations added by translators, managers can also invite and remove project members, upload source and translation files to the project, set up integrations, etc  </p>
<p>If you want to have a project member who should have access to the features mentioned above, you need to invite a project manager. Alternatively, if you plan to manage the project yourself, it will be enough to invite a proofreader.</p>
</blockquote>
<h2 id="heading-tasks">Tasks</h2>
<p>Organization is the key to the success of any project and Crowdin definitely knows this. This is why they incorporated very helpful tools called tasks on their platform to help you organize your project and coordinate tasks among your team members.</p>
<p>With tasks, you can assign specific files to your translators and proofreaders, set due dates, receive notifications, discuss tasks with other team members, and even split the words from the same file between different team members. </p>
<p>You can also track the status of each task in a visual board where you can drag and drop your tasks from one status to the next. </p>
<p>This sounds great, right? Let's see tasks in more detail.</p>
<h3 id="heading-how-to-create-a-new-task">How to Create a New Task</h3>
<p>To create a new task:</p>
<ul>
<li>Go to your project.</li>
<li>Click on the "Create Task" button.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tasks-tab-section-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks on Crowdin.</em></p>
<p>💡 <strong>Tip:</strong> A task can only be assigned to one project.</p>
<p>After clicking on the button, you will see a form where you can enter all the details of your new task.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/new-task-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Creating a new task.</em></p>
<p>The details that you can enter for a task include:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task information (Part 1).</em></p>
<ul>
<li>Name.</li>
<li>Description.</li>
<li>Type (translate or proofread by own translators or by vendors).</li>
<li>Due date (optional).</li>
<li>Strings assigned to the task (all the strings of the selected file(s) or only strings modified during a specific time period).</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task information (Part 2)</em></p>
<ul>
<li>Filter by labels (the labels that the strings of the task should have).</li>
<li>Exclude labels (the labels that the strings of the task should not have).</li>
<li>You can choose if you would like to skip strings that are already included in other tasks to avoid duplicate work by your team members.</li>
<li>Files that should be translated or proofread.</li>
<li>The target language(s). If the task has more than one target language, the system will create a task for each target language.</li>
<li>To assign team members to the task for each target language, click on the "Assign" option next to each language.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assign-task-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assign button.</em></p>
<p>When you click on "Assign", you will see the following options:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assign-members-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assign team members.</em></p>
<ul>
<li>Select the user(s) that you would like to assign to the task. You can search for users using the filter tool.</li>
<li>If you need to remove a user, just click on it on the list to the right. You can empty the list by clicking on the trash icon.</li>
</ul>
<p>💡 <strong>Tip:</strong> You can also choose if you would like to split the files to assign multiple users to the same file. </p>
<ul>
<li>Once you have all the users selected, click on the "Apply" button.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/select-all-users.png" alt="Image" width="600" height="400" loading="lazy">
<em>Users selected for the task.</em></p>
<p>You will see the profile image of the assigned team members in their corresponding language(s).</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/assigned-members-list-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Assigned team member.</em></p>
<p>Click on "Create Task" to add the new task. Now you will see the task dashboard with a new task in each target language you selected. </p>
<p>In this case, I selected Spanish and assigned myself to the task:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-board-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks dashboard.</em></p>
<h3 id="heading-the-tasks-board">The Tasks Board</h3>
<p>Now it's time to use the tasks board. This board is very helpful to see all the tasks of your project and track their status.</p>
<p>You will immediately notice that there are three possible statuses for a task: </p>
<ul>
<li>To Do</li>
<li>In Progress</li>
<li>Done</li>
</ul>
<p><strong>💡 Tip:</strong> Project managers can move a task from one status to another by dragging and dropping it.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-board-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks dashboard.</em></p>
<p>To see all the tasks in a specific target language, just click on that language and you will see them as "cards" with their corresponding information.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/task-board-2-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Tasks board.</em></p>
<p><strong>💡 Tip:</strong> If a task is assigned to you, you will see a gray star next to the name of the task. You can also search for tasks and filter them. </p>
<h3 id="heading-how-to-filter-tasks-by-members">How to Filter Tasks by Members</h3>
<p>You can see all the tasks assigned to a specific team member by using filters.</p>
<ul>
<li>Click on "Filters".</li>
<li>Click on "All users" (next to "Filter by").</li>
<li>Search for the username of the team member.</li>
<li>Click on the username.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/filter-by-members-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Filter tasks by members.</em></p>
<p>💡 <strong>Tip:</strong> To clear the filter, click on the "Clear filter" option to the right.</p>
<h3 id="heading-task-details">Task Details</h3>
<p>The task details is the basic information and structure of a task. With the details, you can see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-10.17.37-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>A Task.</em></p>
<ul>
<li>If the task is assigned to you (a gray star).</li>
<li>Task number.</li>
<li>Task name.</li>
<li>When the task was created.</li>
<li>If it will be translated and proofread by your own team or by vendors.</li>
<li>The profile pictures of the team members assigned to the task.</li>
<li>Word count.</li>
<li>Number of comments on the task.</li>
</ul>
<p>If you click on the task, you will see a more detailed overview:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/detailed-task-view.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task details.</em></p>
<h3 id="heading-how-to-add-comments-to-a-task">How to Add Comments to a Task</h3>
<p>If you scroll down, you will also have the option to add comments to the task.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/detailed-task-view-2-copy-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Add comments to a task.</em></p>
<h3 id="heading-how-to-change-the-status-of-a-task">How to Change the Status of a Task</h3>
<p>From this detailed view, you will also be able to change the status of the task by just clicking on a button:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/change-status-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task options.</em></p>
<p>If you change the status of a task using these buttons, you will also see the change reflected on the main task board, which would be equivalent to dragging and dropping it into a new status.</p>
<h3 id="heading-how-to-manage-tasks">How to Manage Tasks</h3>
<p>If you click on a task to check its details, and then you click on the three dots at the top right to display more options, you will be able to edit, close, and delete the task.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/edit-a-task-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>More options for managing tasks.</em></p>
<h3 id="heading-how-to-edit-a-task">How to Edit a Task</h3>
<p>This is what you will see if you try to edit a task:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/editing-a-task.png" alt="Image" width="600" height="400" loading="lazy">
<em>Edit task view.</em></p>
<p>It's very similar to what we saw when we created the task. You can change the strings assigned, the files, dates, and you can even reset the task scope and the progress for the assigned files.</p>
<h3 id="heading-how-to-close-a-task">How to Close a Task</h3>
<p>To close a task, you can click on "Close":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/edit-a-task-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>More options for managing tasks.</em></p>
<h3 id="heading-how-to-see-all-closed-tasks">How to See All Closed Tasks</h3>
<p>To see all your closed tasks, you will need to:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Tasks" tab.</li>
<li>Select "Closed" (next to "All").</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/closed-tasks.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>💡 <strong>Tip:</strong> "Done" and "Closed" are a bit different. A task can have the "Done" status but not closed. When a task is has the "Done" status, you will see a button on the card to close it, just like in the image below:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/close-task-when-done-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Close button on a task marked as "Done".</em></p>
<h3 id="heading-how-to-reopen-a-task">How to Reopen a Task</h3>
<p>If you close a task and then realize that you need to reopen it, you just need to:</p>
<ul>
<li>Open the details of the closed task.</li>
<li>Click on the three dots to the right to see additional options.</li>
<li>Choose "Reopen".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/reopen-task.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reopen a task.</em></p>
<p>Now you will see the reopened task on the "To do" column of the tasks board.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/todo-task-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reopened task.</em></p>
<h3 id="heading-how-to-delete-a-task">How to Delete a Task</h3>
<p>To delete a task:</p>
<ul>
<li>Open the task details.</li>
<li>Click on the three dots. </li>
<li>Select "Delete".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/delete-a-task.png" alt="Image" width="600" height="400" loading="lazy">
<em>Delete a task.</em></p>
<h3 id="heading-how-to-see-all-tasks-assigned-to-you">How to See All Tasks Assigned to You</h3>
<p>If you are contributing to a project, you can see all the tasks assigned to you by following these steps:</p>
<ul>
<li>Go to your profile.</li>
<li>Go to the "To do" tab.</li>
<li>You will see all the tasks assigned to you and your archived tasks. </li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/see-all-my-tasks-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>The "To Do" tab on Profile.</em></p>
<p>💡 <strong>Tip:</strong> At the top, you will also find a search field to filter your tasks and an option to filter tasks by project.</p>
<p>This is the basic information that you will see for each task in this view:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/todo-tasks-profile.png" alt="Image" width="600" height="400" loading="lazy">
<em>Task in the "To Do" tab on the profile.</em></p>
<ul>
<li>Task number.</li>
<li>Task status.</li>
<li>Project.</li>
<li>Target language.</li>
<li>Word count.</li>
</ul>
<p>You will also see these two options to:</p>
<ul>
<li>Open the translation editor and start working on the task.</li>
<li>Archive the task.</li>
</ul>
<h3 id="heading-important-question-about-tasks">Important Question about Tasks</h3>
<p>Crowdin mentions this <a target="_blank" href="https://support.crowdin.com/enterprise/tasks/#qa">important question in the documentation</a>:</p>
<blockquote>
<p><strong>Q: <em>How the source file updates affect the existing translation and proofreading tasks?</em></strong>  </p>
<p>A: After the source file update, the list of source strings included in the task will be updated the following way:  </p>
<ul>
<li>The strings removed from the source file during the update will be removed from the task.  </li>
<li>The modified strings marked with the <em>Keep Translations</em> option will appear in the task with the new modified text.  </li>
<li>The newly added strings won’t affect the existing task in any way.  </li>
</ul>
<p>If the source file is restored to the revision, containing the removed strings, they will reappear in the task.</p>
</blockquote>
<h2 id="heading-project-reports">Project Reports</h2>
<p>As a project owner or project manager, reports can very helpful to understand your team's current progress and activity.</p>
<p>Crowdin has a reports feature where you can check your project status. This is a report of the demo project that we have been working with so far: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-reports.png" alt="Image" width="600" height="400" loading="lazy">
<em>Reports tab.</em></p>
<p>To access your project report:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Reports" tab.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.31.20-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Report Part 1.</em></p>
<p>You will see the project status by default and you can switch to cost reports if you need to.</p>
<p>Here you can see some screenshots with the type of data that you can analyze and visualize with these reports:</p>
<ul>
<li>Total project size and the number of translatable strings.</li>
<li>Source language and target language.</li>
<li>Number of members.</li>
<li>Number of managers.</li>
<li>Number of translatable words.</li>
<li>Number of hidden words.</li>
<li>Number of duplicate words.</li>
<li>Number of translated words.</li>
<li>Number of approved words.</li>
<li>Number of new members.</li>
<li>Number of active members.</li>
</ul>
<p>You can see these reports with their corresponding increase or decrease percentage compared to the time period you selected.</p>
<p>You will also find charts of the translation activity with their corresponding legends.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.34.02-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Report (Part 2).</em></p>
<p>You will find charts of the "Proofreading Activity".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.34.11-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>And charts of the "Source Strings Activity", and so on.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.34.13-AM.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can also change the report unit by clicking on this option:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/report-unit.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You can choose: </p>
<ul>
<li>Strings.</li>
<li>Words.</li>
<li>Characters without spaces.</li>
<li>Characters with spaces.</li>
</ul>
<p>On the <a target="_blank" href="https://support.crowdin.com/project-reports/?q=reports">Crowdin documentation</a>, you can find examples of the Translation Activity chart, the Proofreading Activity chart, and the Source Strings Activity chart:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translation-activity-chart-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translation Activity. Image taken from the <a target="_blank" href="https://support.crowdin.com/project-reports/?q=reports">Crowdin documentation</a>.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.41.30-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Proofreading Activity. Image taken from the <a target="_blank" href="https://support.crowdin.com/project-reports/?q=reports">Crowdin documentation</a>.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Screenshot-2023-09-20-at-11.41.46-AM.png" alt="Image" width="600" height="400" loading="lazy">
<em>Source Strings Activity. Image taken from the <a target="_blank" href="https://support.crowdin.com/project-reports/?q=reports">Crowdin documentation</a>.</em></p>
<h3 id="heading-top-members-report">Top Members Report</h3>
<p>Your team members are fundamental for your localization process. Having a detailed report of your most dedicated and productive team members is always helpful. </p>
<p>To generate a report of your top members:</p>
<ul>
<li>Go to your project.</li>
<li>Go to the "Reports" tab.</li>
<li>Click on "Top Members".</li>
<li>Select a date range from the calendar.</li>
<li>Click on "Generate".</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/top-members-report.png" alt="Image" width="600" height="400" loading="lazy"></p>
<p>You will see a list of your top members with:</p>
<ul>
<li>Their target languages</li>
<li>How many strings they translated</li>
<li>Target words</li>
<li>How many strings they approved</li>
<li>How many votes they submitted.</li>
</ul>
<p>You can also export your report in XLSX, CSV or JSON format and display or hide specific columns.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/export-report-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Export options.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/show-or-hide-columns.png" alt="Image" width="600" height="400" loading="lazy">
<em>Display or hide columns.</em></p>
<h2 id="heading-conversations-on-crowdin">Conversations on Crowdin</h2>
<p>Communication is essential for any successful project. You and your team members can communicate directly on Crowdin with the conversations feature.</p>
<p>With this feature, you can communicate with one or more team member in a private chat. Each conversation has a subject, so you can easily find them.</p>
<h3 id="heading-how-to-access-conversations">How to Access Conversations</h3>
<p>To access your conversations:</p>
<p>Click on the conversations icon at the top right, next to your profile picture.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/conversation-button-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Conversations button.</em></p>
<p>Go to "Create Conversation".</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/create-conversations-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Create a Conversation.</em></p>
<p>You can search for users by their name or username and you can also filter users by project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/filter-users.png" alt="Image" width="600" height="400" loading="lazy">
<em>Filter users.</em></p>
<p>This is an example from the <a target="_blank" href="https://support.crowdin.com/conversations/">Crowdin Documentation</a>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-86.png" alt="Image" width="600" height="400" loading="lazy">
<em>Conversation. Image taken from the <a target="_blank" href="https://support.crowdin.com/conversations/">Crowdin documentation</a>.</em></p>
<h3 id="heading-how-to-manage-conversations-and-messages">How to Manage Conversations and Messages</h3>
<p>For conversations, you can:</p>
<ul>
<li>Change the subject for all the users in the conversation.</li>
<li>Mute the conversation to stop receiving notifications.</li>
<li>Add users.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-87.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example conversation. Image taken from the <a target="_blank" href="https://support.crowdin.com/conversations/">Crowdin documentation</a>.</em></p>
<p>For individual messages within a conversation, you can:</p>
<ul>
<li>Share the message in the same conversation or in another conversation. </li>
<li>Mark the message as unread.</li>
<li>Edit your messages.</li>
<li>Delete your messages.</li>
<li>Report spam.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-88.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of managing messages. Image taken from the <a target="_blank" href="https://support.crowdin.com/conversations/#messages">Crowdin documentation</a>.</em></p>
<p>🎉 Awesome. Now you know the most important features of Crowdin for teams and organizations.</p>
<p>Let's dive into how you can integrate Crowdin with other services and how you can install apps to improve your productivity.</p>
<h2 id="heading-crowdin-integrations-and-productivity-tools">🔹 Crowdin Integrations and Productivity Tools</h2>
<p>One of the key characteristics of Crowdin is its connectivity. You can connect your project to different external services to import and export your files and translations as needed.</p>
<h2 id="heading-what-is-an-integration">What is an Integration?</h2>
<p>On Crowdin, an integration is a "connection" that you can make between your project and an external service to synchronize your files between these platforms automatically.</p>
<p>On the <a target="_blank" href="https://store.crowdin.com/">Crowdin store</a>, you can find over 600 apps and integrations that you can add to your project.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Crowdin-store.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Crowdin Store.</em></p>
<p>You can filter them by:</p>
<ul>
<li>Collections.</li>
<li>Categories.</li>
<li>Partners.</li>
<li>QA Checks.</li>
</ul>
<p>To give you an idea of the types of apps and integrations that you can find, these are some of the featured apps and integrations:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/featured-integrations.png" alt="Image" width="600" height="400" loading="lazy">
<em>Featured apps and integrations.</em></p>
<p>Let's talk about a few of them in more detail. </p>
<h3 id="heading-github-integration">GitHub Integration</h3>
<p>If your project is hosted on a GitHub repository, the <a target="_blank" href="https://store.crowdin.com/github">GitHub integration</a> could be exactly what you need.</p>
<blockquote>
<p>Crowdin’s integration with GitHub synchronizes source and translation files between your GitHub repository and translation project in Crowdin. All translated and approved files will be automatically pushed as a pull request to the l10n branch in GitHub repository.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/GitHub-integration.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Integration.</em></p>
<p>To learn more about this integration, you can check out <a target="_blank" href="https://www.youtube.com/watch?v=8baL6VWnnZg">this tutorial</a> created by Crowdin.</p>
<h3 id="heading-github-crowdin-action">GitHub Crowdin Action</h3>
<p>If you need to upload and download files from your GitHub repository to your Crowdin project automatically, this action can be very helpful for you.</p>
<p>The <a target="_blank" href="https://store.crowdin.com/github-action">GitHub Crowdin Action</a> can:</p>
<ul>
<li>Upload source files to Crowdin.</li>
<li>Upload translations to Crowdin.</li>
<li>Downloads translations from Crowdin.</li>
<li>Create a PR with the translations.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/github-crowdin-action.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Crowdin Action.</em></p>
<p>To learn more about the GitHub Crowdin Action, check out <a target="_blank" href="https://www.youtube.com/watch?v=5b7BMuCoKGg">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-google-drive-integration">Google Drive Integration</h3>
<p>Google Drive is very helpful to create, host, and share documents. With the Google Drive integration, you can translate your files very easily on Crowdin.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/google-drive-integration.png" alt="Image" width="600" height="400" loading="lazy">
<em>Google Drive Integration.</em></p>
<p>To learn more about this integration, you can check out <a target="_blank" href="https://www.youtube.com/watch?v=M_WbdDQmEP8">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-ai-assistant">AI Assistant</h3>
<p>With the rise in popularity of Large Language Models (LLMs), artificial intelligence has become a very important tool for translation and localization. </p>
<p>Crowdin has a very helpful <a target="_blank" href="https://store.crowdin.com/localization-ai">AI Assistant</a> that you can install to help you and your team. It is described as:</p>
<blockquote>
<p>An AI chatbot for translators built on OpenAI’s ChatGPT API. The first version of this app works as a co-pilot for translators. (<a target="_blank" href="https://store.crowdin.com/localization-ai">Source: Crowdin</a>)</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/ai-assistant.png" alt="Image" width="600" height="400" loading="lazy">
<em>AI Assistant.</em></p>
<p>Crowdin mentions that the AI Assistant has these interesting features:</p>
<blockquote>
<p>Our AI Assistant has a prompt engineering feature, empowering translators to customize prompts before commencing a translation project. As a result, they can conveniently modify the context, enhancing precision and meaningful translations.</p>
</blockquote>
<p>To learn more about this integration, check out <a target="_blank" href="https://www.youtube.com/watch?v=DSEu0iQanc4">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-visual-studio-code-integration">Visual Studio Code Integration</h3>
<p>If you are a developer who works with <a target="_blank" href="https://store.crowdin.com/visual-studio-code">Visual Studio Code</a>, then Crowdin also has you covered because the team developed an extension to help you to translate your project.</p>
<blockquote>
<p>Integrate your Visual Studio Code projects with Crowdin to optimize the localization process. <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Crowdin.vscode-crowdin">IDE Plugin</a> allows uploading new source strings instantly to your Crowdin project and downloading translations. (<a target="_blank" href="https://store.crowdin.com/visual-studio-code">Source: Crowdin</a>)</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/visual-studio-code.png" alt="Image" width="600" height="400" loading="lazy">
<em>Visual Studio Code Integration.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/vs-code-extension.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Extensions Marketplace.</em></p>
<p>You can learn more about this extension on its <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=Crowdin.vscode-crowdin">official documentation</a> in the Visual Studio Code Extensions Marketplace.</p>
<h3 id="heading-video-captions-translator">Video Captions Translator</h3>
<p>If you or your organization need to translate video captions, Crowdin has an integration for that too. It is called <a target="_blank" href="https://store.crowdin.com/video-captions-translator">Video Captions Translator</a>.</p>
<blockquote>
<p>Professional translations for video subtitles. Setup integration once, define your localization workflow and spend less time managing translations.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/video-captions-translator.png" alt="Image" width="600" height="400" loading="lazy">
<em>Video Captions Translator.</em></p>
<p>To learn more about YouTube Captions Translation with Crowdin, you can check out <a target="_blank" href="https://store.crowdin.com/video-captions-translator">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-google-sheets-integration">Google Sheets Integration</h3>
<p>If you use <a target="_blank" href="https://store.crowdin.com/spreadsheet-crowdin">Google Sheets</a> to manage your localization keys, you can add this integration to your project to map your columns to their corresponding fields on Crowdin, including:</p>
<ul>
<li>Key.</li>
<li>Source Text.</li>
<li>Target Languages (all project languages).</li>
<li>Labels.</li>
<li>Context.</li>
<li>Translation Maximum Length.</li>
</ul>
<p>Please note that the Crowdin team mentions that:</p>
<blockquote>
<p>It's worth noting that this integration will only sync the first sheet from your Google Sheet document.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/google-sheets.png" alt="Image" width="600" height="400" loading="lazy">
<em>Google Sheets Integration.</em></p>
<p>To learn more about the Google Sheets Integration, check out <a target="_blank" href="https://www.youtube.com/watch?v=7tOanqDiIJ8">this tutorial</a> created by the Crowdin team. </p>
<h3 id="heading-suggestions-diff-checker">Suggestions Diff Checker</h3>
<p>If you have ever asked for a tool that could help your translators and proofreaders compare translations very easily with visual cues, this app is for you. </p>
<p>Crowdin describes <a target="_blank" href="https://store.crowdin.com/diff-checker">Suggestions Diff Checker</a> as:</p>
<blockquote>
<p>A great helper for proofreaders and translators that compares two translations and shows the difference between them.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/suggestions-diff-checker.png" alt="Image" width="600" height="400" loading="lazy">
<em>Suggestions Diff Checker.</em></p>
<h3 id="heading-proofreading-diff">Proofreading Diff</h3>
<p>Proofreading is a very important task for the localization process. Proofreaders can edit the translations and make sure that they are as accurate as possible. </p>
<p>With the <a target="_blank" href="https://store.crowdin.com/proofreading-diff">Proofreading Diff</a> report app, you can:</p>
<blockquote>
<p>Track and analyze changes made during the proofreading process. This tool can help you provide a thorough feedback to translators about their work.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/proofreading-diff.png" alt="Image" width="600" height="400" loading="lazy">
<em>Proofreading Diff.</em></p>
<h3 id="heading-video-preview">Video Preview</h3>
<p>Translating the subtitles of a video without actually watching the video simultaneously can be quite challenging because having the full context of a string is very helpful to translate it accurately. </p>
<p>This is why Crowdin created a translator productivity app called <a target="_blank" href="https://store.crowdin.com/preview-video">Video Preview</a>. They describe it as:</p>
<blockquote>
<p>A handy tool that can be useful when you have video subtitles to translate. It allows you to specify the video URL for each file with subtitles, and enables translators to preview the video while working on the translation.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/video-preview.png" alt="Image" width="600" height="400" loading="lazy">
<em>Video Preview.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-96.png" alt="Image" width="600" height="400" loading="lazy">
<em>Video Preview in action. Image taken from the <a target="_blank" href="https://store.crowdin.com/preview-video">Crowdin Documentation</a>.</em></p>
<h3 id="heading-glossary-editor">Glossary Editor</h3>
<p>This is another helpful Crowdin application for managing your project glossaries.</p>
<p>Crowdin mentions that the <a target="_blank" href="https://store.crowdin.com/glossary-edit-app">Glossary Editor</a>:</p>
<blockquote>
<p>Allows you to add and change the terms from your glossaries directly in Crowdin Editor.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/glossary-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>Glossary Editor.</em></p>
<h3 id="heading-project-duplicator">Project Duplicator</h3>
<p>Have you ever wished that you could use a project as a template for another project and save yourself all the initial set up time?</p>
<p>If you have, then <a target="_blank" href="https://store.crowdin.com/create-project-app">Project Duplicator</a> is exactly what you need:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-duplicator.png" alt="Image" width="600" height="400" loading="lazy">
<em>Project Duplicator.</em></p>
<p>With Project Duplicator, you can copy the following settings from a project:</p>
<ul>
<li>Source language.</li>
<li>Quality assurance checks.</li>
<li>Source strings.</li>
<li>Translations.</li>
<li>Translation Memory.</li>
<li>Notifications.</li>
<li>Language Mapping.</li>
</ul>
<h3 id="heading-unity-integration">Unity Integration</h3>
<p>If you are a game developer and you work with Unity, this integration is exactly what you need.</p>
<p>With the <a target="_blank" href="https://store.crowdin.com/unity">Unity Integration</a>, you can:</p>
<blockquote>
<p>Translate the content within your tables (strings and assets) and download translations into Unity.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/unity.png" alt="Image" width="600" height="400" loading="lazy">
<em>Unity Integration.</em></p>
<p>This is an official screenshot of the Crowdin Plugin for Unity:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-101.png" alt="Image" width="600" height="400" loading="lazy">
<em>Imagen taken from the <a target="_blank" href="https://store.crowdin.com/unity">Crowdin Documentation</a>.</em></p>
<h3 id="heading-is-crowdin-slow-for-everyone-or-just-me">Is Crowdin slow for everyone or just me?</h3>
<p>Yes, this is the official name of a translator productivity tool in Crowdin! 🙂 It is a performance widget for measuring your internet connection. </p>
<p>Crowdin <a target="_blank" href="https://store.crowdin.com/internet-speed">mentions</a> that it can be helpful to:</p>
<blockquote>
<p>Know immediately if the slowness you experience is caused by your internet connection or it's a Crowdin performance issue.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/is-crowdin-slow.png" alt="Image" width="600" height="400" loading="lazy">
<em>Is Crowdin slow for everyone or just me?</em></p>
<p>This is an official screenshot of the widget:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-97.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image taken from the <a target="_blank" href="https://store.crowdin.com/internet-speed">Crowdin Documentation</a>.</em></p>
<h3 id="heading-units-converter">Units Converter</h3>
<p>You learned that localization is broader than translation. Units are a great example of this. </p>
<p>When you localize a product that includes units of length, area, mass, volume, temperature, speed, and more, you need to have a tool at hand to convert them quickly while you localize your content. </p>
<p>Crowdin mentions that:</p>
<blockquote>
<p>The app is especially convenient when localizing for cultures that use different measurement systems.</p>
</blockquote>
<p>This is where the <a target="_blank" href="https://store.crowdin.com/units_converter">Units Converter app</a> can save you a lot of time because you can have it on your Translation Editor and quickly convert units without pausing your localization process to go to another tool.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/units-converter.png" alt="Image" width="600" height="400" loading="lazy">
<em>Units Converter.</em></p>
<p>This is an official screenshot of the app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-98.png" alt="Image" width="600" height="400" loading="lazy">
_Units Converter app. Image taken from the <a target="_blank" href="https://store.crowdin.com/units_converter">Crowdin Documentation</a>._</p>
<h3 id="heading-screenshots-uploader">Screenshots Uploader</h3>
<p>Visual context is essential for writing high-quality translations. </p>
<p>The <a target="_blank" href="https://store.crowdin.com/screenshots-uploader">Screenshots Uploader</a> app:</p>
<blockquote>
<p>Makes it easier for your team to receive visual context.</p>
</blockquote>
<p>You can:</p>
<ul>
<li>Allow translators to upload screenshots. </li>
<li>Paste screenshots from your clipboard history without saving them on your device.</li>
<li>Edit screenshots before uploading them with helpful tools like cropping, zooming in, and so on.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/screenshots-uploader.png" alt="Image" width="600" height="400" loading="lazy">
<em>Screenshots Uploader.</em></p>
<h3 id="heading-directory-notifications">Directory Notifications</h3>
<p>The <a target="_blank" href="https://store.crowdin.com/directory-notification">Directory Notifications</a> app is helpful for project owners and managers because Crowdin will:</p>
<blockquote>
<p>Send an email notification whenever a directory of files in your Crowdin project gets translated or proofread.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/directory-notifications.png" alt="Image" width="600" height="400" loading="lazy">
<em>Directory Notifications.</em></p>
<p>This is an official screenshot of the app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-100.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image taken from the <a target="_blank" href="https://store.crowdin.com/directory-notification">Crowdin Documentation</a>.</em></p>
<h3 id="heading-emoji-input-for-editor">Emoji Input for Editor</h3>
<p>Emojis are awesome, right? I think we can all agree on that. 😁 </p>
<p>Luckily for us, Crowdin has an <a target="_blank" href="https://store.crowdin.com/emoji">Emoji Input for the Translation Editor</a>. They describe it as:</p>
<blockquote>
<p>A Crowdin Editor emoji list app for easy access with an extensive search functionality.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/emoji-input.png" alt="Image" width="600" height="400" loading="lazy">
<em>Emoji Input for Editor.</em></p>
<p>This is an official screenshot of the app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-99.png" alt="Image" width="600" height="400" loading="lazy">
<em>Image taken from the <a target="_blank" href="https://store.crowdin.com/emoji">Crowdin Documentation</a>.</em></p>
<h3 id="heading-emoji-mismatch">Emoji Mismatch</h3>
<p>And now let's dive into helpful automated Quality Assurance (QA) checks for our project that are available for Enterprise Crowdin accounts.</p>
<p>The first one is <a target="_blank" href="https://store.crowdin.com/emoji-mismatch-custom">Emoji Mismatch</a>, which can help us to find:</p>
<blockquote>
<p>Missed, extra or mismatched emoji in the translation.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/Emoji-Mismatch.png" alt="Image" width="600" height="400" loading="lazy">
<em>Emoji Mismatch.</em></p>
<p>Please note that this works with Crowdin Enterprise.</p>
<h3 id="heading-space-after-punctuation">Space After Punctuation</h3>
<p>This is a very helpful quality assurance tool that you can add to your project.</p>
<p>Crowdin mentions that <a target="_blank" href="https://store.crowdin.com/space-after-punctuation-custom">Space After Punctuation</a>:</p>
<blockquote>
<p>Checks whether the translation contains the spaces after the punctuation symbols.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/space-after-punctuation.png" alt="Image" width="600" height="400" loading="lazy">
<em>Space After Punctuation.</em></p>
<p>Please note that this works with Crowdin Enterprise. </p>
<h3 id="heading-url-localization">URL Localization</h3>
<p>This is a quality assurance tool that you can also install for your project. With <a target="_blank" href="https://store.crowdin.com/url-localization-custom">URL localization</a>, you can check:</p>
<blockquote>
<p>Mistakes in URLs in the translation according to QA check configuration.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/url-localization.png" alt="Image" width="600" height="400" loading="lazy">
<em>URL Localization.</em></p>
<p>Please note that this works with Crowdin Enterprise. </p>
<h3 id="heading-duplicated-words">Duplicated Words</h3>
<p>This is a great tool for the proofreading phase of the localization project. Crowdin mentions that <a target="_blank" href="https://store.crowdin.com/duplicated-words-custom">Duplicated Words</a>:</p>
<blockquote>
<p>Removes every second repeated word in translation.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/duplicated-words.png" alt="Image" width="600" height="400" loading="lazy">
<em>Duplicated words.</em></p>
<p>Please note that this works with Crowdin Enterprise. </p>
<h3 id="heading-time-format-consistency">Time Format Consistency</h3>
<p>Writing time in a consistent format is also very important when you are localizing a product.</p>
<p>Crowdin <a target="_blank" href="https://store.crowdin.com/time-format-consistency">mentions</a> that:</p>
<blockquote>
<p>This QA check verifies that time formats in the source and translated text match. It checks for time formats in the 24-hour format (HH:MM).</p>
<p>The QA check will give a positive result if the number and format of time instances are consistent between the source and translated text, and a negative result if there is a mismatch.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/time-format-consistency.png" alt="Image" width="600" height="400" loading="lazy">
<em>Time Format Consistency.</em></p>
<p>Please note that this works with Crowdin Enterprise. </p>
<h3 id="heading-camelcase-consistency-check">camelCase Consistency Check</h3>
<p>This quality assurance check helps you ensure that product names, brand names, or other names that should be written in camelCase follow the same format in the translation.</p>
<p>Crowdin <a target="_blank" href="https://store.crowdin.com/camelcase-check">mentions</a> that it:</p>
<blockquote>
<p>Validates that all camelCase words present in the source text are accurately retained in the translated text.</p>
<p>If a camelCase word in the source text is not found in the translated text, the check will fail and notify the translator with a detailed message.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/camelcase-consistency-check.png" alt="Image" width="600" height="400" loading="lazy">
<em>camelCase Consistency Check.</em></p>
<h3 id="heading-more-apps-and-integrations">More Apps and Integrations</h3>
<p>We have seen many helpful apps and integrations for your localization process. They can optimize your team's productivity and help you to provide high-quality translations.</p>
<p>But this is just the start. Crowdin has more than 600 apps and integrations for your project. You can find a full list on the <a target="_blank" href="https://store.crowdin.com/categories/all">Crowdin Store</a>. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-store-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Crowdin Store.</em></p>
<p>If you click on them, you will find more details about what they do, how they do it, and you may even find the source code that implements the functionality.</p>
<p>You can also sort them by relevance, name, or date. </p>
<p>The tools that you need to be more productive and deliver high-quality translations to your users are just one click away. </p>
<h2 id="heading-how-to-translate-a-website-on-crowdin">🔹 How to Translate a Website on Crowdin</h2>
<p>Great work! We've reached a very important part of the book, how to translate a website on Crowdin.</p>
<h3 id="heading-how-to-translate-a-website-on-crowdin-1">How to Translate a Website on Crowdin</h3>
<p>There are three main approaches for translating a website on Crowdin:</p>
<ul>
<li>Integrations.</li>
<li>JS Proxy Translator.</li>
<li>Crowdin In-context.</li>
</ul>
<p>Since there are many technologies, frameworks, and libraries for web development and the internationalization process is very technology-specific, it is recommended to analyze all the options available and find the one that works best for your particular use case.</p>
<h3 id="heading-integrations-1">Integrations</h3>
<p>The web development world is incredibly diverse. We can create and host websites on a variety of services and develop them using different tools.</p>
<p>To support this variety of tools and services, Crowdin has developed many integrations with external platforms to import your text and send your translations to the Content Management System (CMS) of your choice.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translate-website-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Translate a Website on Crowdin.</em></p>
<p>For example, you can translate a website from WordPress, Webflow, Joomla, and other similar tools. </p>
<p>According to <a target="_blank" href="https://crowdin.com/blog/2020/12/17/website-translation-with-crowdin">Crowdin</a>:</p>
<blockquote>
<p>With Crowdin, you are not confined to any specific website building and hosting services.</p>
<p>We do not only have 15 apps, including <a target="_blank" href="https://store.crowdin.com/wix-proxy-translator">Wix</a>, <a target="_blank" href="https://store.crowdin.com/ghost-org-proxy-translator">Ghost</a>, <a target="_blank" href="https://store.crowdin.com/squarespace-proxy-translator">Squarespace</a> and <a target="_blank" href="https://store.crowdin.com/webflow-proxy-translator">Webflow</a>, that provide you with the best way to translate a website, but a separate <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">JS Proxy</a> technology that will help you with the localization of any other website.</p>
</blockquote>
<p>Essentially, these technologies:</p>
<ul>
<li>Scan your web pages.</li>
<li>Detect the content that can be translated (strings).</li>
<li>Extract them in a format that can be localized.</li>
<li>Synchronize the translations with your original project.</li>
</ul>
<p>You just need to add a JavaScript snippet to your code and you will be ready to start translating.</p>
<p>These are some of the apps that you can install to start translating your website on various external services:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/apps-for-translation.png" alt="Image" width="600" height="400" loading="lazy">
<em>A list of Crowdin apps that you can install to <a target="_blank" href="https://crowdin.com/blog/2020/12/17/website-translation-with-crowdin">translate your website</a>.</em></p>
<p>If host your repository on GitHub or you use GitHub pages, you can also use Crowdin's <a target="_blank" href="https://store.crowdin.com/github">GitHub Integration</a> and the <a target="_blank" href="https://store.crowdin.com/github-action">GitHub Crowdin Action</a> to synchronize your website files and translations automatically.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/github-integrations.png" alt="Image" width="600" height="400" loading="lazy">
<em>GitHub Integrations.</em></p>
<h3 id="heading-js-proxy-translator">JS Proxy Translator</h3>
<p>Integrations are very helpful, but Crowdin also has an option that can help you with the localization of any website, irrespective of the service where it is hosted. </p>
<p>This approach to website localization on Crowdin is called <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">JS Proxy Translator</a>. </p>
<p>Crowdin mentions that with this proxy, you can:</p>
<ul>
<li>Synchronize your sources and translated content.</li>
<li>Localize your website with minimum effort.</li>
<li>Extract source text without any coding.</li>
<li>Translate meta titles and description to be SEO-friendly.</li>
<li>Schedule when to synchronize your translations.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/js-proxy.png" alt="Image" width="600" height="400" loading="lazy">
<em>JS Proxy Translator.</em></p>
<p>Here we have two official screenshots provided by the Crowdin team that shows the steps required to configure the JS Proxy Translator. </p>
<p>The first step is to import your website content. You just need to enter your site URL and specify if you would like to sync the source files manually or daily by importing them automatically once a day.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-104.png" alt="Image" width="600" height="400" loading="lazy">
<em>JS Proxy Translator (Part 1). Image taken from the <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">Crowdin documentation</a>.</em></p>
<p>Then, after your source text is translated, you can publish the translations to your website.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-105.png" alt="Image" width="600" height="400" loading="lazy">
<em>JS Proxy Translator (Part 2). Image taken from the <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">Crowdin documentation</a>.</em></p>
<p>The Crowdin team does <a target="_blank" href="https://store.crowdin.com/js-proxy-translator">mention</a> that:</p>
<blockquote>
<p>You need to publish all content on your website before synchronizing it to your project for translation.</p>
</blockquote>
<p>To learn more about how to translate a website with a JS Proxy on Crowdin, check out <a target="_blank" href="https://www.youtube.com/watch?v=q_0byyBDRGI">this tutorial</a> created by the Crowdin team.</p>
<h3 id="heading-in-context-for-web">In-Context for Web</h3>
<p>The third approach to website localization on Crowdin is to translate the text directly within the website or web application using Crowdin In-Context.</p>
<p>The Crowdin team <a target="_blank" href="https://store.crowdin.com/in-context">mentions</a> that:</p>
<blockquote>
<p>Crowdin In-Context tool allows to translate texts directly within the actual web application. In such a way, the best translation quality is maintained.  </p>
<p>In-Context localization is tied up with the actual project created in Crowdin, under which translatable files are stored.  </p>
<p>This tool makes all the texts in the web app editable. Moreover, the translation process is real-time visible. Even the dynamic part of the application and strings that contain placeholders can be translated this way.</p>
</blockquote>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/crowdin-in-context.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin In-Context.</em></p>
<p>You can see it in action <a target="_blank" href="https://demo.crowdin.com/">here</a>, in the official Crowdin demo:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-website.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin In-Context Demo.</em></p>
<p>If you log in to your Crowdin account, you will see this:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/demo-website-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Crowdin In-Context Demo.</em></p>
<p>You will be able to click on each string on the website to translate it and when you save the translations, they will be synchronized with your Crowdin project.</p>
<p><strong>💡 Tip:</strong> To learn more about Crowdin In-Context, check out <a target="_blank" href="https://www.youtube.com/watch?v=ktfw7UsW3qw">this tutorial</a> created by the Crowdin team.</p>
<p>These are three different approaches for translating a website on Crowdin. Choosing the right one can make all the difference for your localization team. </p>
<p>Now that you know more about the most important Crowdin features, let's dive into freeCodeCamp's translation effort as a real-world example of a worldwide localization project powered by contributions from an amazing community of volunteers.</p>
<h2 id="heading-freecodecamps-translation-effort">🔹 freeCodeCamp's Translation Effort</h2>
<p>🎉 Awesome. Congratulations on reaching this part of the book. This proves that you are very interested in learning these skills.</p>
<p>Now that you know how to translate your project on Crowdin, let's see how freeCodeCamp's amazing community is translating our content into many world languages.</p>
<p>We'll see this from a potential contributor's point of view, emphasizing how to translate our content on Crowdin.</p>
<h3 id="heading-freecodecamps-contributing-guidelines">freeCodeCamp's Contributing Guidelines</h3>
<p>If you are a contributor who is interested in joining the translation effort, where should you start? </p>
<p>You should start by reading our <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files">Contributing Guidelines</a>. These are a set of articles that you can always refer to if you have any questions on how to join or how to start translating and proofreading. </p>
<p>There, you will find:</p>
<ul>
<li>A written overview of Crowdin.</li>
<li>How to get started.</li>
<li>How to select a project and a file.</li>
<li>How to translate the projects that we have on Crowdin. </li>
<li>How to proofread translations.</li>
<li>Translation best practices, and more!</li>
</ul>
<p>In <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files">this article</a>, you will find information on how to prepare yourself for contributions. </p>
<p>We recommend:</p>
<ul>
<li>Reading <a target="_blank" href="https://www.freecodecamp.org/news/help-translate-freecodecamp-language/">this announcement</a> written by Quincy Larson, the founder of freeCodeCamp. </li>
<li>Joining the <a target="_blank" href="https://forum.freecodecamp.org/c/contributors/3">community forum</a>. </li>
<li>Joining our <a target="_blank" href="https://discord.gg/PRyKn3Vbay">Discord chat server</a>.</li>
</ul>
<p>Our <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files">documentation</a> also mentions that working with a small team can be super helpful to stay motivated:</p>
<blockquote>
<p>Crowdin and other tools make it easy to contribute translations, but it's still a lot of work.  </p>
<p>We want you to enjoy contributing and not burn out or lose interest.  </p>
<p>A small group of 4-5 individuals is a good size to start your niche for your world language. You can then recruit even more friends to join the team.</p>
</blockquote>
<p>Currently, we have over 30 of the most widely spoken languages enabled on our Crowdin project. </p>
<p>Some of them are deployed on the live version of freeCodeCamp. You just need to select them from the dropdown menu to see a new language automatically.</p>
<p>If you do not see your languages listed, the documentation also mentions that:</p>
<blockquote>
<p>If you would like us to include a new world language, we recommend getting your friends excited about this.  </p>
<p>Once you have a small group of people (at least 4-5) interested and committed, we can hop on a call. We will explain all the details and walk you through some of the tools and processes.</p>
</blockquote>
<p>Once you have finished reading this part of the contributing guidelines, you can start to contribute. </p>
<p>First, let's take a look at the different roles that you can have as a freeCodeCamp contributor.</p>
<h3 id="heading-roles-for-the-freecodecamp-localization-process">Roles for the freeCodeCamp Localization Process</h3>
<p>You can contribute to freeCodeCamp's translation effort as a translator or proofreader.</p>
<p>Translators help us to translate curriculum files, documentation, and elements of freeCodeCamp's user interface like buttons and labels.</p>
<p>Proofreaders make sure that the translations are consistent, uniform in tone, and free from common issues such as typos.</p>
<h3 id="heading-language-leads">Language Leads</h3>
<p>Our language leads will be very happy to welcome you to our translation effort:</p>
<ul>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/farhanhasin/">Farhan Hasin Chowdhury</a> (<a target="_blank" href="https://twitter.com/frhnhsin">@frhnhsin</a>) is leading the Bengali community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/chinese/news/author/miyaliu/">Miya Liu</a> (<a target="_blank" href="https://twitter.com/miyaliu666">@miyaliu666</a>) is leading the Chinese community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/italian/news/author/dario/">Dario Di Cillo</a> (<a target="_blank" href="https://twitter.com/_dariodc">@_DarioDC</a>) is leading the Italian community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/japanese/news/author/yoko/">Yoko Matsuda</a> (<a target="_blank" href="https://twitter.com/_sidemt">@_sidemt</a>) is leading the Japanese community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/korean/news/author/alison-yoon/">Alison Yoon</a> (<a target="_blank" href="https://twitter.com/aliyooncreative">@aliyooncreative</a>) is leading the Korean community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/daniel/">Daniel Rosa</a> (<a target="_blank" href="https://twitter.com/Daniel__Rosa">@Daniel__Rosa</a>) is leading the Portuguese community. </li>
<li><a target="_blank" href="https://www.freecodecamp.org/portuguese/news/author/nielda/">Nielda Karla Gonçalves de Melo</a> (<a target="_blank" href="https://twitter.com/NieldaKarla">@NieldaKarla</a>) is leading the Portuguese community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/rafael/">Rafael Hernandez</a> (<a target="_blank" href="https://twitter.com/rafaeldavish">@RafaelDavisH</a>) is leading the Spanish community and the localization process.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/espanol/news/author/estefaniacn">Estefania Cassingena Navone</a> (<a target="_blank" href="https://twitter.com/EstefaniaCassN">@EstefaniaCassN</a>) is leading the Spanish YouTube channel.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/larymak/">Hillary Nyakundi</a> (<a target="_blank" href="https://twitter.com/larymak1">@larymak1</a>) is leading the Swahili community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/ukrainian/news/author/anastasiia/">Anastasiia Buievych</a> (<a target="_blank" href="https://twitter.com/anisiangel?s=21&amp;t=3yJxu9lXXPDyxB6WYhRsWg">@anisiangel</a>) is leading the Ukrainian community.</li>
<li><a target="_blank" href="https://www.freecodecamp.org/news/author/zaira/">Zaira Hira</a> (<a target="_blank" href="https://twitter.com/hira_zaira">@hira_zaira</a>) is leading the Urdu community.</li>
</ul>
<h3 id="heading-freecodecamp-on-crowdin">freeCodeCamp on Crowdin</h3>
<p>Just like I mentioned before, Crowdin is the translation platform we use. It is a localization management platform where individuals, teams, and organizations can localize their resources efficiently.</p>
<p>To access freeCodeCamp's projects on Crowdin:</p>
<p>Go to <a target="_blank" href="https://translate.freecodecamp.org/">translate.freecodecamp.org</a> and you will see the dashboard with the projects that we are currently focused on:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/freecodecamp.png" alt="Image" width="600" height="400" loading="lazy">
<em>freeCodeCamp.org on Crowdin.</em></p>
<p>We have three main projects:</p>
<ul>
<li><a target="_blank" href="https://translate.freecodecamp.org/curriculum">Coding Curriculum</a></li>
<li><a target="_blank" href="https://translate.freecodecamp.org/learn-ui">Learn User Interface</a></li>
<li><a target="_blank" href="https://translate.freecodecamp.org/contributing-docs">Contributing Documentation</a></li>
</ul>
<p>We also have other projects on Crowdin such as News UI, Other Courses, and Subtitles (Chinese).</p>
<h3 id="heading-how-to-choose-a-project-and-a-language">How to Choose a Project and a Language</h3>
<p>Once you're on our translation platform, you will need to choose a project. Let's say that you choose to translate the coding curriculum. </p>
<p>You just need to click on the project:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/freecodecamp-dashboard-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>Click on the project you would like to contribute work.</em></p>
<p>Once you click on the project, you will be taken to a list of available languages for translation.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-in-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>List of available languages for the Coding Curriculum project.</em></p>
<p>For each language, you will see:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/language.png" alt="Image" width="600" height="400" loading="lazy"></p>
<ul>
<li>Its name.</li>
<li>Its language code.</li>
<li>A bar with two possible colors. Blue represents the translation progress and green represents the proofreading progress. </li>
<li>You can also see their corresponding percentages to the right.</li>
<li>The last number to the right represents the number of words to translate.</li>
</ul>
<p>You will also find an information panel on the right with:</p>
<ul>
<li>A brief description of the project.</li>
<li>The source language (English).</li>
<li>The number of contributors for that project.</li>
<li>How many source words exist in the project.</li>
<li>When the project was created and when it was last active.</li>
</ul>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/project-in-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>Check out the information on the right (the gray panel).</em></p>
<p>Now it's time to choose a language. </p>
<p>If you click on the language, you will be taken to the project structure with all the files and folder available for translation. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/spanish-modern-files-crowdin.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Coding Curriculum project structure for Spanish (Modern).</em></p>
<h4 id="heading-how-to-select-a-file">How to Select a File</h4>
<p>To enter the Translation Editor and start translating, just click on the name of a file that needs translation. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/selecting-a-file.png" alt="Image" width="600" height="400" loading="lazy">
<em>Select a file that needs translation. A file needs translation if the bar is not completely blue (translated) or green (proofread).</em></p>
<p>Please note that we usually prioritize translating the first three certifications.</p>
<p>💡 <strong>Tip:</strong> if you are not signed in to your Crowdin account or if you have not created your Crowdin account yet, you will be prompted to do so when you click on a file. </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/creating-an-account.png" alt="Image" width="600" height="400" loading="lazy">
<em>This is the screen where you can log in to freeCodeCamp's translation platform. You can also sign up to create your Crowdin account.</em></p>
<p>If you're signing up for a new account, you will need to enter your email, choose your username, and your password. You will also receive an email from Crowdin asking you to click on a link to verify your email address. </p>
<h3 id="heading-the-translation-editor">The Translation Editor</h3>
<p>Congratulations. Now you have your Crowdin account and you are ready to start translating the file you selected. </p>
<p>Let's say that you clicked on the <code>**build-a-drum-machine.md**</code> file and you want to translate it into Spanish (Modern).</p>
<p>You will see a screen similar to this one:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/the-translator-ui.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translation Editor. This is what you will see when you click on a file and sign in to your Crowdin account.</em></p>
<p>If you would like to learn more about how the editor works, click on "Next" to see more tips on the UI but if you would like to close this short tutorial, just click on the X at the top. </p>
<p>These are the seven steps of the short tutorial provided by Crowdin in case you would like to keep them as a reference:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-2.png" alt="Image" width="600" height="400" loading="lazy">
<em>Collaborate on translations in real-time.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-3.png" alt="Image" width="600" height="400" loading="lazy">
<em>Use context to make relevant translations.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-4.png" alt="Image" width="600" height="400" loading="lazy">
<em>Preview files.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-5.png" alt="Image" width="600" height="400" loading="lazy">
<em>Make translations from any device.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-6.png" alt="Image" width="600" height="400" loading="lazy">
<em>Switch to Side-by-side view to review translations faster.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/tutorial-step-7.png" alt="Image" width="600" height="400" loading="lazy">
<em>That's all friends! This is the seventh and last step of the tutorial.</em></p>
<p>After you reach the final step, click "Close" and you will be in the Translation Editor. </p>
<p>This is where the magic happens. You can start translating, save your translations, use suggested translations and adapt them, and even upvote or downvote proposed translations. </p>
<p>To translate a string, just click on it or save your current translation to go to the next string.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translations-editor.png" alt="Image" width="600" height="400" loading="lazy">
<em>The Translations Editor.</em></p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/translations-editor-copy.png" alt="Image" width="600" height="400" loading="lazy">
<em>This is where you can write and save your translation.</em></p>
<p>💡 <strong>Tip:</strong> You can also write comments and mark them as issues to notify freeCodeCamp's staff and other contributors.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/comments-sample.png" alt="Image" width="600" height="400" loading="lazy">
<em>You can write comments for individual strings and mark them as issues.</em></p>
<h3 id="heading-how-to-translate-the-learn-interface">How to Translate the Learn Interface</h3>
<p>We also have specific guidelines for translating the Learn interface.</p>
<p>Our <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=translate-the-learn-interface">documentation</a> mentions that:</p>
<blockquote>
<p>Our <code>/learn</code> interface relies on JSON files loaded into an i18n plugin to generate translated text. This translation effort is split across both Crowdin and GitHub.</p>
</blockquote>
<p>We translate the <code>intro.json</code> and <code>translations.json</code> files on Crowdin. If you are planning to translate strings from these files, please know that the Context information provided in Crowdin can be very helpful.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/image-68.png" alt="Image" width="600" height="400" loading="lazy">
<em>Example of the context information provided by Crowdin (<a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=on-crowdin">source</a>).</em></p>
<p>There are certain files that we cannot upload to Crowdin, such as <code>links.json</code>, <code>meta-tags.json</code>, <code>motivation.json</code>, and <code>trending.json</code>. These files are usually maintained by language leads but if you would like to help with these, please refer to <a target="_blank" href="https://contribute.freecodecamp.org/#/language-lead-handbook">this article</a>.</p>
<h3 id="heading-how-to-translate-the-documentation">How to Translate the Documentation</h3>
<p>Documentation is another essential resource for freeCodeCamp's mission because we can share important information, steps, and guidelines with potential contributors. </p>
<p>We do have certain guidelines for translating our documentation. You can <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=translate-documentation">find them</a> in this article. It covers how to translate internal links in the translated documentation.</p>
<h3 id="heading-best-practices">Best Practices</h3>
<p>For any project, our goal should always be to follow the best practices, right? These are some of the <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=translation-best-practices">best practices</a> that you should follow to translate freeCodeCamp's resources:</p>
<ul>
<li>Do not translate the content within <code>&lt;code&gt;</code> tags. These tags indicate text that is found in code and should be left in English.</li>
<li>Do not add additional content. If you feel a challenge requires changes in the text content or additional information, you should propose the changes through a GitHub issue or a pull request that modifies the English file.</li>
<li>Do not change the order of content.</li>
</ul>
<h3 id="heading-how-to-become-a-proofreader">How to Become a Proofreader</h3>
<p>If you join freeCodeCamp's localization effort, you can also <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-proofread-files?id=becoming-a-proofreader">become a proofreader</a>.</p>
<p>We will typically grant you proofreading access if you have been contributing to freeCodeCamp for a while.</p>
<p>If you would like to apply to become a proofreader, please reach out to us in our <a target="_blank" href="https://discord.gg/PRyKn3Vbay">contributors chat room</a>.</p>
<p>💡 <strong>Tip:</strong> Proofreaders can approve their own translations. However, we advise you to allow another proofreader to review your proposed translations to make sure that there are no errors or typos.</p>
<h3 id="heading-how-to-proofread-the-translations">How to Proofread the Translations</h3>
<p>When you become a proofreader, you will have special permissions in the Translations Editor. You will be able to see the current translations, edit them, and approve them.</p>
<p>You should consider the community scores determined by the upvotes and the downvotes when deciding which translations to approve.</p>
<p>When you approve a string, the automated process that we configured with the <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-proofread-files?id=proofread-translations">GitHub integration</a> on Crowdin will add it to our live platform:</p>
<blockquote>
<p>Approving a string in the proofreading view will mark it as complete and it will be downloaded in our next pull from Crowdin to GitHub.</p>
</blockquote>
<h3 id="heading-discord-chat-server-for-translators">Discord Chat Server for Translators</h3>
<p>If you have any questions or you would like to join our translation effort, you are welcome to join our <a target="_blank" href="https://contribute.freecodecamp.org/#/how-to-translate-files?id=prepare-yourself-for-contributions">Discord chat server</a> for translators.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/09/discord-chat-room.png" alt="Image" width="600" height="400" loading="lazy">
<em>Our Discord chat server.</em></p>
<p>Once you create your account and join the server, you will see a welcome message with the <code>**#start-here**</code> localization channel.</p>
<p>Excellent work. Now you are ready to start translating and join freeCodeCamp's localization effort.</p>
<h2 id="heading-summary">Summary</h2>
<p>Congratulations! We covered many topics related to localization and now you know more about how to localize your resources and platforms to reach users worldwide.</p>
<p>These are some key takeaways:</p>
<ul>
<li>In a globalized world where information is available with just a few clicks, localizing products, services, and platforms is essential if your goal is to reach users worldwide. Adapting them to different cultures will open doors for your team, your organization, and users around the world.</li>
<li>Crowdin is a powerful localization management platform focused on giving you and your team the tools you need to localize products and platforms that are constantly evolving. </li>
<li>freeCodeCamp's localization effort is a real-world example of a global community brought together by a common goal: providing free access to education around the world without language barriers. You can join too.</li>
</ul>
<p>I hope you liked this book on localization fundamentals. You are ready to start localizing your platform. Now is the right time to start. Localization can be exactly what you need to reach a global community of users.</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ The Regular Expressions Book – RegEx for JavaScript Developers [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ If you want to master regular expressions and understand how they work in JavaScript, this book's for you. Regular expressions can be intimidating when you first encounter them. When I started learning to code, I gave up on regular expressions twice.... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/regular-expressions-for-javascript-developers/</link>
                <guid isPermaLink="false">66adf1f6f452caf50fb1fe18</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ JavaScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regex ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Regular Expressions ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ Kolade Chris ]]>
                </dc:creator>
                <pubDate>Wed, 26 Jul 2023 15:27:12 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/07/Regex-for-JavaScript-Developers-Cover.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>If you want to master regular expressions and understand how they work in JavaScript, this book's for you.</p>
<p>Regular expressions can be intimidating when you first encounter them. When I started learning to code, I gave up on regular expressions twice.</p>
<p>While that was partly because I was intimidated by regular expressions at first, the tutorials and courses I used never taught them in a way I could understand. </p>
<p>In fact, before some tutorials start teaching regex, they complain about regex and how tough they can be. And there's no better way to discourage a learner than that.</p>
<p>In this book, you won't just see how to use regex in a regex testing tool like <strong>regexpal</strong> or <strong>regex101</strong>. You'll also see how they works in JavaScript. This is what many courses and tutorials tailored for regex in JavaScript lack. As you see how they work using a regex tester, you'll also see how they work in JavaScript.</p>
<p>You can also apply what you learn in this book to other programming languages like Python, PHP, and so on. All you need to do is to know about how the regex engine of that language works. You'll also need to understand the methods and functions the language uses for working with regular expressions.</p>
<p>To get the most out of this book, make sure you read it in order because each chapter builds upon the previous ones. I have also arranged the chapters according to how difficult they are. So, you will find simpler concepts first and more advanced concepts later.</p>
<p>Happy reading!</p>
<h2 id="heading-table-of-contents">Table Of Contents</h2>
<ul>
<li><a class="post-section-overview" href="#heading-chapter-1-introduction-to-regular-expressions">Chapter 1: Introduction to Regular Expressions</a><ul>
<li><a class="post-section-overview" href="#heading-what-are-regular-expressions">What are Regular Expressions?</a></li>
<li><a class="post-section-overview" href="#heading-a-brief-history-of-regular-expressions">A Brief History of Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-what-are-the-uses-of-regular-expressions">What are the Uses of Regular Expressions?</a></li>
<li><a class="post-section-overview" href="#heading-flavors-of-regular-expressions">Flavors of Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-tools-for-working-with-regular-expressions">Tools for Working with Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-basic-concepts-of-regular-expressions">Basic Concepts of Regular Expressions</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-2-how-to-match-literal-characters-and-character-sets-in-regular-expressions">Chapter 2: How to Match Literal Characters and Character Sets in Regular Expressions</a><ul>
<li><a class="post-section-overview" href="#heading-what-are-literal-characters-in-regular-expressions">What are Literal Characters in Regular Expressions?</a></li>
<li><a class="post-section-overview" href="#heading-how-to-match-literal-characters-in-regex-testers">How to Match Literal Characters in RegEx Testers</a></li>
<li><a class="post-section-overview" href="#heading-character-set-matching">Character Set Matching</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-3-regular-expressions-flags">Chapter 3: Regular Expressions Flags</a><ul>
<li><a class="post-section-overview" href="#heading-the-global-flag">The <code>global</code> Flag</a></li>
<li><a class="post-section-overview" href="#heading-the-case-insensitive-flag">The <code>case-insensitive</code> Flag</a></li>
<li><a class="post-section-overview" href="#heading-the-multi-line-and-single-line-flags">The <code>multi-line</code> and <code>single-line</code> Flags</a></li>
<li><a class="post-section-overview" href="#heading-the-unicode-flag">The <code>unicode</code> Flags</a></li>
<li><a class="post-section-overview" href="#heading-the-sticky-flag">The <code>sticky</code> Flags</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-4-how-to-use-regular-expressions-in-javascript">Chapter 4: How to Use Regular Expressions in JavaScript </a><ul>
<li><a class="post-section-overview" href="#heading-how-to-create-regular-expressions-in-javascript">How to Create Regular Expressions in JavaScript</a></li>
<li><a class="post-section-overview" href="#heading-methods-of-the-regexp-constructor">Methods of the <code>RegExp()</code> Constructor</a></li>
<li><a class="post-section-overview" href="#heading-properties-of-the-regexp-constructor">Properties of the <code>RegExp()</code> Constructor</a></li>
<li><a class="post-section-overview" href="#heading-string-methods-for-working-with-regular-expressions">String Methods for Working with Regular Expressions</a></li>
<li><a target="_blank" href="howtomatchliteralcharactersinjavascriptregularexpressions">How to Match Literal Characters in JavaScript Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-character-sets-in-javascript-regular-expressions">How to Use Character Sets in JavaScript Regular Expressions</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-5-metacharacters-quantifiers-repeated-matches-and-optional-matches">Chapter 5: Metacharacters, Quantifiers, Repeated Matches, and Optional Matches</a><ul>
<li><a class="post-section-overview" href="#heading-what-are-metacharacters">What are Metacharacters?</a></li>
<li><a class="post-section-overview" href="#heading-the-word-and-non-word-metacharacters">The Word and Non-word Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-anchor-metacharacters">The Anchor Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-digit-and-non-digit-metacharacters">The Digit and Non-digit Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-square-brackets-metacharacter">The Square Brackets Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-the-word-boundary-and-non-word-boundary-metacharacters">The Word Boundary and Non-word Boundary Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-parenthesis-metacharacter">The Parenthesis Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-the-space-and-non-space-metacharacters">The Space and Non-space Metacharacters</a></li>
<li><a class="post-section-overview" href="#heading-the-pipe-metacharacter">The Pipe Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-how-to-match-repeated-characters-with-quantifiers">How to Match Repeated Characters With Qunatifiers</a></li>
<li><a class="post-section-overview" href="#heading-how-to-specify-match-quantity-with-the-curly-braces-metacharacter">How to Specify Match Quantity with the Curly Braces Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-the-wildcard-metacharacter">The Wildcard Metacharacter</a></li>
<li><a class="post-section-overview" href="#heading-greediness-and-laziness-in-regular-expressions">Greediness and Laziness in Regular Expressions</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-6-grouping-and-capturing-in-regex">Chapter 6: Grouping and Capturing in Regex</a><ul>
<li><a class="post-section-overview" href="#heading-how-to-reference-captured-groups-with-backreferences">How to Reference Captured Groups with Backreferences</a></li>
<li><a class="post-section-overview" href="#heading-how-to-use-the-d-flag-and-hasindices-property-with-groups">How to Use the <code>d</code> Flag and <code>hasIndices</code> Property With Groups</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-7-lookaround-groups-lookaheads-and-lookbehinds">Chapter 7: Lookaround Groups: Lookaheads and Lookbehinds</a> <ul>
<li><a class="post-section-overview" href="#heading-what-are-lookaround-groups">What are Lookaround Groups?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-a-lookahead-group">What is a Lookahead Group?</a></li>
<li><a class="post-section-overview" href="#heading-what-is-a-lookbehind-group">What is a Lookbehind Group?</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-8-regex-best-practices-and-troubleshooting">Chapter 8: Regex Best Practices and Troubleshooting</a><ul>
<li><a class="post-section-overview" href="#heading-best-practices-to-consider-while-writing-regular-expressions">Best Practices to Consider While Writing Regular Expressions</a></li>
<li><a class="post-section-overview" href="#heading-how-to-write-accurate-regular-expressions">How to Write Accurate Regular Expressions</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-chapter-9-applications-of-regular-expressions">Chapter 9: Applications of Regular Expressions</a><ul>
<li><a class="post-section-overview" href="#heading-a-better-way-to-match-dates">A Better Way to Match Dates</a> </li>
<li><a class="post-section-overview" href="#heading-how-to-match-us-zip-codes">How to Match US Zip Codes</a></li>
<li><a class="post-section-overview" href="#heading-how-to-match-email-addresses">How to Match Email Addresses</a></li>
<li><a class="post-section-overview" href="#heading-how-to-match-passwords">How to Match Passwords</a></li>
<li><a class="post-section-overview" href="#heading-form-validation-with-regex">Form Validation with Regex</a></li>
<li><a class="post-section-overview" href="#heading-article-table-of-contents-generator">Article Table of Contents Generator</a></li>
</ul>
</li>
<li><a class="post-section-overview" href="#heading-glossary-and-references">Glossary and References</a><ul>
<li><a class="post-section-overview" href="#heading-glossary-of-terms">Glossary of Terms</a> </li>
<li><a class="post-section-overview" href="#heading-quick-reference-of-metacharacters-and-quantifiers">Quick Reference of Metacharacters and Quantifiers</a> </li>
</ul>
</li>
</ul>
<h2 id="heading-chapter-1-introduction-to-regular-expressions">Chapter 1: Introduction to Regular Expressions</h2>
<h3 id="heading-what-are-regular-expressions">What are Regular Expressions?</h3>
<p>You might see this written as regular expressions, regex, or RegExp – but all refer to the same thing. </p>
<p>Regex are a sequence of characters for matching a part of a string or the whole string. Matching strings with regular expressions might require more than just "characters". Many times, you will need to use a special set of characters called "metacharacters" and "quantifiers". </p>
<p>Because regular expressions are a powerful tool, you can use then to do much more than just "matching strings" when you combine regex with programming languages. </p>
<p>Almost all the main programming languages of the modern era have built-in support for regular expressions. Some programming languages might even have specific libraries that help you work more conveniently with regex.</p>
<p>Apart from using regular expressions in programming languages, other tools that let you use regular expressions are:</p>
<ul>
<li><p><strong>Text Editors and IDEs</strong>: for search and search and replace in VS Code, Visual Studio, Notepad++, Sublime Text, and others.</p>
</li>
<li><p><strong>Browser Developer Tools</strong>: mostly in-browser search (with extensions or add-ons) and search within the developer tools.</p>
</li>
<li><p><strong>Database Tools</strong>: for data mining.</p>
</li>
<li><p><strong>RegEx Testers</strong>: you can paste in text and write the regular expressions to match them – which is a very good way to learn regular expressions. This book explores that option quite a bit.</p>
</li>
</ul>
<h3 id="heading-a-brief-history-of-regular-expressions">A Brief History of Regular Expressions</h3>
<p>Regular expressions have a rich and fascinating history that has already spanned more than seven decades. This history continues to evolve alongside the development of computer science and programming languages.</p>
<p>The concept of regular expressions traces back to the 1950s. American mathematician Stephen Cole Kleene introduced them as a notation for defining patterns in formal languages. Kleene's work also formed the foundation for theoretical computer science.</p>
<p>In the early 1960s, the first implementations of regular expressions emerged. Ken Thompson, a computer scientist at Bell Labs, developed a text editor named <strong>QED</strong> that utilized regular expressions for pattern matching. QED's capabilities provided a way to search and manipulate texts more efficiently.</p>
<p>The concept gained further popularity when Thompson and Dennis Ritchie created the Unix operating system in the early 1970s. </p>
<p>They incorporated regular expressions into various Unix utilities, most notably the <strong>ed text editor</strong> and later the <strong>sed stream editor</strong>. These tools allowed users to perform complex text manipulation tasks, significantly enhancing the efficiency and power of text processing.</p>
<p>In 1973, Thompson collaborated with Alfred Aho and Peter Weinberger to develop a new tool called <strong>grep</strong> (global regular expression print) as part of the Unix toolkit. </p>
<p>Grep allowed users to search files for specific patterns using regular expressions. The simplicity and effectiveness of grep made it a widely adopted tool. It also established regular expressions as a standard feature in Unix-based systems.</p>
<p>As computer systems and programming languages evolved, regular expressions became integrated into various software development environments. In the late 1970s, the AWK programming language was created. AWK inspired Larry Wall to create Perl and make it available to the public in 1987.</p>
<p>Wall recognized the value of regular expressions for text manipulation and integrated regex into Perl. </p>
<p>Perl's integration of regular expressions into its syntax made it a popular language for text matching and data extraction tasks. This integration formed the foundation of  <strong>PCRE</strong> (Perl-compatible regular expressions), a flavor and library of regular expressions you can use in some programming languages such as Perl, Python, PHP, Java, and others.</p>
<p>Regular expressions continued to evolve and find applications beyond Unix and Perl. In the 1980s, the International Organization for Standardization (ISO) developed the POSIX standard, which included a specification for regular expressions. This standardization ensured compatibility and consistency across different implementations and systems.</p>
<p>With the rise of the internet and the World Wide Web in the 1990s, regular expressions found widespread use in web development and data processing. They became an essential component of many scripting languages, providing developers with powerful tools for text processing, form validation, and data extraction from web pages. </p>
<p>For example, JavaScript had always had a version of PCRE built in for working with regular expressions. But by 1999, with the release of ECMAScript, the <code>RegExp()</code> constructor was introduced. This gave JavaScript developers the ability to start using regular expressions directly in their code, in the JavaScript way.</p>
<p>In the early 2000s, tools and libraries specifically focused on regular expressions emerged, making it easier for developers to work with them. Libraries like PCRE (Perl Compatible Regular Expressions) provided enhanced features and better performance, further expanding the usage and capabilities of regular expressions.</p>
<p>Today, regular expressions are an integral part of programming languages and text-processing tools like your code editor. They are supported by almost all major programming languages, including Java, C#, Ruby, and PHP. </p>
<p>Integrated development environments (IDEs) and code editors like Visual Studio, VS Code, and Notepad++ also now include regex-based search and search and replace functionalities, simplifying the process of finding and manipulating texts in code. </p>
<p>The history of regular expressions demonstrates their evolution from theoretical concepts to practical tools that have revolutionized text processing and pattern matching. </p>
<p>From the early developments at Bell Labs and Unix to their integration into popular programming languages, regular expressions have become an essential tool in the hands of developers and system administrators. Regex empowers them to handle complex text-based tasks efficiently. </p>
<p>With the ongoing advancements in computing and the continuous demand for efficient text processing, regular expressions will likely remain a fundamental part of the technology landscape for years to come.</p>
<h3 id="heading-what-are-the-uses-of-regular-expressions">What are the Uses of Regular Expressions?</h3>
<p>Regular expressions are quite versatile and flexible. This makes it possible to apply them to various tasks in various domains such as computer programming, data processing, text editing, and web development.</p>
<p>Those applications and uses include but are not limited to the following:</p>
<p><strong>String Matching</strong>: This is one of the most common ways developers use regular expressions. This is also a good way to learn regular expressions. </p>
<p>You can paste some texts into a regex engine and write the regex to match a part of the text or the whole text. You can also search for strings that contain specific character sequences, start or end with certain characters, or match complex patterns. </p>
<p>This makes regular expressions valuable for tasks like searching for keywords, validating input against specific patterns, or filtering data based on string patterns</p>
<p><strong>Password Strength Validation</strong>: You can use regular expressions for validating the strength of passwords in websites and applications. </p>
<p>By defining a set of rules using regular expressions, developers can enforce specific password requirements, such as a minimum number of characters, a combination of uppercase and lowercase letters, numbers, and special characters. </p>
<p><strong>Form Validation</strong>: Validating inputs of a form or standalone inputs is another popular way developers use regular expressions. </p>
<p>Regular expressions provide a concise and efficient way to ensure that input data follows specific patterns or formats. Whether it's validating usernames, email addresses, phone numbers, credit card numbers, postal codes, or other inputs, regular expressions can help you enforce validation rules and maintain data integrity.</p>
<p><strong>Text Search and Manipulation</strong>: Regular expressions excel at searching for specific patterns within text and performing manipulations based on those matches. They are a powerful tool for tasks such as data mining, log analysis, and text processing. </p>
<p>Whether you need to find occurrences of particular words or phrases, extract structured data from text, analyze content, or perform string matching, regular expressions offer efficient pattern-matching capabilities</p>
<p><strong>Working with URLs and URIs</strong>: Since URLs and URIs are an integral part of web development, regular expressions can help in validating, parsing, and manipulating them. This enables developers to ensure the correctness and structure of web addresses, validate whether a string is a valid URL, and help extract specific components such as the domain, path, query parameters, or fragments. </p>
<p>This functionality is particularly useful in tasks like URL routing, rewriting, or extracting data from query parameters.</p>
<p><strong>Search and Replace in IDEs and Text Editors</strong>: Regular expressions offer sophisticated search capabilities. This enables developers to locate specific patterns (such as words with specific prefixes or sequences of characters) and then replace the matches with a specified text. This is built into modern text editors like VS Code and Notepad++.</p>
<p><strong>Data Extraction and Scraping</strong>: Regular expressions play a significant role in data extraction and web scraping. They allow developers to extract specific information from unstructured or semi-structured text by defining patterns to match desired data. </p>
<p>They are also valuable when extracting data from sources like HTML or XML documents, as they enable efficient retrieval of information based on defined patterns.</p>
<p><strong>Syntax Highlighting</strong>: Regular expressions are commonly used in IDEs and text editors to provide syntax highlighting. This ends up helping users to visually distinguish different parts of a code or document by assigning colors or formatting to keywords, strings, comments, and other language-specific constructs. </p>
<p>Regular expressions are used to identify and match these language-specific patterns, making code more readable and enhancing the overall editing experience.</p>
<h3 id="heading-flavors-of-regular-expressions">Flavors of Regular Expressions</h3>
<p>The term "flavors of regular expressions" refers to the specific implementation and syntax variations of regular expressions in different programming languages, libraries, or tools. </p>
<p>While the core concept of regular expressions remains the same, the details of how regular expressions are written and interpreted can vary between different environments.</p>
<p>Each flavor of regular expressions may have its own set of metacharacters, syntax rules, and additional features beyond the basic functionality. </p>
<p>These differences can include variations in the syntax for character classes, metacharacters, capturing groups, and assertions, as well as additional capabilities like named capturing groups, look-ahead, and look-behinds.</p>
<p>There are many flavors of regular expressions available today. Some of them are:</p>
<ul>
<li><p><strong>Basic Regular Expressions (BRE)</strong>: this flavor is commonly found in Unix tools such as <strong>sed</strong> and <strong>grep</strong>. It uses a limited set of metacharacters and features. The wildcard (<code>.</code>) and zero or more (<code>*</code>) metacharacters are available in it.</p>
</li>
<li><p><strong>Extended Regular Expressions (ERE)</strong>: ERE is an extension of BRE. It provides additional metacharacters and features. In addition to the metacharacters available in BRE, ERE introduces features like grouping with parentheses ( <code>( )</code>), alternation with the pipe symbol (<code>|</code>), and the use of curly braces (<code>{}</code>) to specify repetition ranges.</p>
</li>
<li><p><strong>Perl-Compatible Regular Expressions (PCRE)</strong>: PCRE is a popular flavor supported by various programming languages such as Perl, Python, PHP, and JavaScript. PCRE extends the basic regular expression syntax with powerful features like lookahead and look-behind assertions, backreferences, non-capturing groups, and the use of <code>\b</code> for word boundaries.</p>
</li>
<li><p><strong>JavaScript Regular Expressions</strong>: JavaScript has its regular expression flavor which is similar to PCRE but with a few differences. It supports basic features like character classes with square brackets (<code>[ ]</code>), metacharacters (<code>*</code>, <code>+</code>, <code>?</code>, and others), and capturing groups  (<code>( )</code>). JavaScript also provides additional features like the global flag <code>/g</code> to perform multiple matches, and the ignore case flag <code>/i</code> for case-insensitive matching</p>
</li>
<li><p><strong>Python Regular Expressions</strong>: Python's <code>re</code> module implements a flavor that is similar to PCRE but with a few variations. It supports features such as character classes <code>[ ]</code>, metacharacters (<code>*</code>, <code>+</code>, and <code>?</code>), and capturing groups (<code>( )</code>). The <code>re</code> module also has a unique raw string syntax (<code>r' '</code>) to simplify working with backslashes.</p>
</li>
</ul>
<p>It's important to be aware of the flavor of regular expressions you are using when working with regular expressions in different programming languages or tools. This ensures that you use the correct syntax and take advantage of any unique features or capabilities provided by that particular flavor.</p>
<p><strong>N.B.</strong>: Don’t bother so much about the metacharacters (and quantifiers) mentioned in this part. You will see them in action in chapter 5 of this book.</p>
<h3 id="heading-tools-for-working-with-regular-expressions">Tools for Working with Regular Expressions</h3>
<p>Regular expression tools are the programming languages, libraries and frameworks, command line utilities, online regex testers, text editors and IDEs, and applications designed to help you create, test, and apply regular expressions in your day-to-day work life.</p>
<p>There are many tools available for working with regular expressions. Let me take you through them under regex testers, programming languages, libraries, text editors and IDEs, and command line tools.</p>
<h4 id="heading-regex-testers">RegEx Testers</h4>
<p>RegEx testers are the online testing environments specifically built for creating and testing regular expressions against some test strings. Examples include regex101.com, regexr.com, and regexpal.com.</p>
<p>The UIs of these regex testers usually have an input for the regular expressions you want to write, and another for the text you want to test the regex against. </p>
<p>This is how the UI of regexpal.com looks:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regexpal-ui.png" alt="regexpal-ui" width="600" height="400" loading="lazy"></p>
<p>More advanced ones like regex101.com let you select the flavor of regular expressions you want to work with, an explanation of the regex, and match information. </p>
<p>Here’s what the UI of regex101.com looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regex101-ui-1.png" alt="regex101-ui-1" width="600" height="400" loading="lazy"></p>
<p>One of the good things about these online regex testers is that they are helpful for learning regular expressions. A lot of them provide real-time matching and cheatsheets you can quickly look at. Many devs who use regex have used them. </p>
<p>Apart from learning, you can also use them by creating your regex with them and pasting them into wherever you want to use the regex. This is how I create my regex.</p>
<h4 id="heading-programming-languages">Programming Languages</h4>
<p>Almost all modern programming languages have built-in support for regular expressions. And so they all have methods for creating and testing regular expressions. </p>
<p>For example, JavaScript has the <code>RegExp()</code> constructor for working with regular expressions, Python has the <code>re</code> module, Java has the <code>java.util.regex</code> package, and Perl has regex built into it directly.</p>
<h4 id="heading-libraries-and-frameworks">Libraries and Frameworks</h4>
<p>Many programming languages have standalone libraries and frameworks that make it easier to create regular expressions. </p>
<p>There is <code>XRegExp</code> for JavaScript, PCRE (Perl Compatible Regular Expressions) for Perl, Go-Restructure for Golang, and Verbal Expressions, a cross-platform regex library.</p>
<h4 id="heading-text-editors-and-ides">Text Editors and IDEs</h4>
<p>Many text editors and IDEs such as VS Code, Visual Studio, Notpad++, Atom, Sublime Text, IntelliJ IDEA, and others have built-in support for regular expressions. </p>
<p>The commonest thing developers use this for is search, and search and replace. Also, the syntax highlighting in those text editors and IDEs is often implemented with regular expressions.</p>
<h4 id="heading-command-line-tools">Command Line Tools</h4>
<p>Unix command line tools like grep and sed allow you to perform regex operations on text files and streams. With this, you can search, filter, and manipulate multiple files. </p>
<p>Using these Unix tools, options for customizing search behaviors and customizing complex text transformations are also available to you.</p>
<h3 id="heading-basic-concepts-of-regular-expressions">Basic Concepts of Regular Expressions</h3>
<p>The basic concepts and syntax of regular expressions are the building blocks involved in creating, testing, and applying patterns for searching, matching, and manipulating strings. </p>
<p>This includes concepts like <strong>literal characters</strong>, <strong>metacharacters</strong>, <strong>quantifiers</strong>, <strong>character classes</strong>, <strong>anchors and boundaries</strong>, and <strong>escape characters</strong>. The more advanced ones are <strong>groupings</strong>, <strong>backreferences</strong>, <strong>look-ahead assertions</strong>, and <strong>look-behind assertions</strong>.</p>
<p>Regular expressions users utilize many of these concepts to construct efficient regular expressions for working with text. On many occasions, the basic ones are enough. But if you want to create more advanced regular expressions, then the more advanced ones will also be useful for you.</p>
<p>This book won’t leave any of the concepts behind. I will show you how you can utilize them in regex testers and how you can use them in JavaScript since that’s what this book is meant for.</p>
<h2 id="heading-chapter-2-how-to-match-literal-characters-and-character-sets-in-regular-expressions">Chapter 2: How to Match Literal Characters and Character Sets in Regular Expressions</h2>
<h3 id="heading-what-are-literal-characters-in-regular-expressions">What are Literal Characters in Regular Expressions?</h3>
<p>Literal characters are characters you can match as they appear in a test string. They could be letters, numbers, spaces, or even symbols. In other words, they are non-special characters that represent themselves.</p>
<p>This means if you want to match literal characters, you should construct your regex pattern in the same way as the test string appears. </p>
<p>For example, if you want to match the word <code>hello</code>, your regex pattern can be <code>hello</code>. And if you want to match the <code>h</code> in the word <code>hatch</code>, all you need as the pattern is <code>h</code>. </p>
<p>This <code>h</code> would match the first occurrence of the letter <code>h</code> in the test string <code>hatch</code>. If you want it to match the other letter <code>h</code> as well, you need the "g" flag, or global flag. You will learn about the flags and modifiers in the next chapter of this book.</p>
<p>That is not the case for some symbols, though. That’s because some symbols are special characters of regular expressions (metacharacters and quantifiers). So, if you want to match those characters, you have to escape them with a backslash (<code>\</code>). This book will also teach you all you need to know about metacharacters because there's a whole chapter for them.</p>
<h3 id="heading-how-to-match-literal-characters-in-regex-testers">How to Match Literal Characters in RegEx Testers</h3>
<p>Provided you want to match the word <code>hello</code>, then <code>hello</code> should be your regex pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/hello-match-1.png" alt="hello-match-1" width="600" height="400" loading="lazy"></p>
<p>If you want to match the text <code>freeCodeCamp</code>, you can construct your regex to be <code>freeCodeCamp</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/fcc-match-1.png" alt="fcc-match-1" width="600" height="400" loading="lazy"></p>
<p>So, what if you want to match <code>hello freeCodeCamp</code>? Then you just use <code>hello freeCodeCamp</code> as the pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/hello-fcc-match.png" alt="hello-fcc-match" width="600" height="400" loading="lazy"></p>
<p>If you want to match the letter <code>e</code> in the text <code>freeCodeCamp</code>, <code>e</code> is the pattern to use:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/e-in-fcc.png" alt="e-in-fcc" width="600" height="400" loading="lazy"></p>
<p>And if you want to match <code>h</code> in the text <code>hatch</code>, <code>h</code> is the pattern you should use:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/h-in-hatch.png" alt="h-in-hatch" width="600" height="400" loading="lazy"></p>
<p>You can see that in the text <code>freeCodeCamp</code>, the other <code>e</code>s after the first occurrence were not returned as matches – same with the last <code>h</code> in the word <code>hatch</code>. You will learn how to match every occurrence of a letter in a text in the next chapter.</p>
<h3 id="heading-character-set-matching">Character Set Matching</h3>
<p>A character set, also called character class, is a set of characters that will successfully match a certain character in a test string. This set of characters is enclosed in square brackets. </p>
<p>For instance, the pattern <code>[abc]</code> will match any of <code>a</code>, <code>b</code>, and <code>c</code>, while <code>[xyz]</code> will match any of <code>x</code>, <code>y</code>, and <code>z</code>.</p>
<p>Here are some examples of character sets and what they do:</p>
<ul>
<li><code>[abc]</code>: matches either <code>a</code>, <code>b</code>, or <code>c</code></li>
<li><code>[aeiou]</code>: matches any vowel character</li>
<li><code>[a-z]</code>: matches any lowercase letter from <code>a</code> to <code>z</code></li>
<li><code>[A-Z]</code>: matches any uppercase letter from <code>A</code> to <code>Z</code></li>
<li><code>[0-9]</code>: matches any digit from 0 to 9</li>
</ul>
<p>Inside the square brackets, you don’t need to escape metacharacters because they lose their special meaning. The only symbol that has a meaning in the square brackets is a hyphen (<code>-</code>), which you can use to specify ranges, as I have done with some examples of character sets. </p>
<p>You will also learn about ranges in this book. On some occasions, a backslash <code>\</code> does not lose its special meaning in a character set.</p>
<p>As with literal character matching, only the first occurrence of the character set will return as a match, every other occurrence will be ignored. In the next chapter, you will learn how to match multiple occurrences of a character with the <code>g</code> flag.</p>
<p>Here’s how each of the above character sets works in a regex testing tool:</p>
<p><code>[abc]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/-abc--match.png" alt="-abc--match" width="600" height="400" loading="lazy"></p>
<p><code>[aeiou]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/vowels-match.png" alt="vowels-match" width="600" height="400" loading="lazy"></p>
<p><code>[a-z]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/lcase-set-match.png" alt="lcase-set-match" width="600" height="400" loading="lazy"></p>
<p><code>[A-Z]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/ucase-set-match.png" alt="ucase-set-match" width="600" height="400" loading="lazy"></p>
<p><code>[0-9]</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/number-set-match.png" alt="number-set-match" width="600" height="400" loading="lazy"></p>
<p>You can also define your unique character class based on what you want. Character sets are useful when you want to match some characters in a particular position in a text.</p>
<p>For instance, the pattern <code>br[ao]ke</code> will match both <code>brake</code> and <code>broke</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/brakebroke-match.png" alt="brakebroke-match" width="600" height="400" loading="lazy"></p>
<p>The pattern <code>gr[ae]y</code> will match both <code>gray</code> and <code>grey</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/graygrey-match.png" alt="graygrey-match" width="600" height="400" loading="lazy"></p>
<p><strong>N.B.</strong>: I turned on the <code>g</code> flag so you can see all the matches, and how powerful character sets are. We will take a look at the <code>g</code> and other flags in the next chapter.</p>
<p>Since there are always multiple ways of doing the same thing in programming, there are also certain character sets called "shorthand character sets" that you can use instead of character sets. </p>
<p>Since these shorthand character sets are a subset of metacharacters, you will learn about them under the chapter dedicated to metacharacters.</p>
<h2 id="heading-chapter-3-regular-expressions-flags">Chapter 3: Regular Expressions Flags</h2>
<p>Also called modifiers, flags are special characters you can place at the end or within a regular expressions pattern to alter its default behavior. </p>
<p>JavaScript developers tend to refer to these characters as "flags", but in Python they are used interchangeably. </p>
<p>In Python, you can place flags within a regex pattern, but in JavaScript, flags are always placed at the end of the regex pattern.</p>
<p>Here are the flags you can use in regular expressions:</p>
<ul>
<li><code>global</code> flag</li>
<li><code>case insensitive</code> flag</li>
<li><code>multi-line</code> flag</li>
<li><code>single-line</code> flag</li>
<li><code>unicode</code> flag</li>
<li><code>sticky</code> flag</li>
</ul>
<p>In many regex engines, you can turn on any flag you want to use. In regex101.com, you can turn on a flag by clicking on the slash symbol (<code>/</code>) right inside the pattern input: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/turn-on-a-flag-101.png" alt="turn-on-a-flag-101" width="600" height="400" loading="lazy"></p>
<p>You can then select any flag you want to use:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/select-flag-101.png" alt="select-flag-101" width="600" height="400" loading="lazy"></p>
<p><strong>N.B.</strong>: If the flavor of regex you selected in regex101.com is not ECMAScript, the set of flags presented to you might be different.</p>
<p>If you are using regexpal.com, click on "flags" above the regex pattern input:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/turn-on-flag-pal.png" alt="turn-on-flag-pal" width="600" height="400" loading="lazy"></p>
<p>Select any flag you want by clicking on it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/select-flag-pal.png" alt="select-flag-pal" width="600" height="400" loading="lazy"></p>
<p>Now, let's take a detailed look at each of the regex flags and how they work in a regex engine.</p>
<h3 id="heading-the-global-flag">The <code>global</code> Flag</h3>
<p>The <code>global</code> flag is denoted by the letter <code>g</code>. With it, you get to perform a global match with your pattern. </p>
<p>Remember in the previous chapter of this book, some patterns I defined stopped when they found the first match, even if there were more. That’s because by default, regular expressions only find the first match in a text. But with the <code>g</code> flag, all occurrences of the match are returned.</p>
<p>Another good thing about using the <code>g</code> flag is that you can iterate over the matches you get with the pattern in JavaScript. The iteration continues until there’s nothing to match. You will learn about multiple ways you can iterate over matches soon.</p>
<p>To let you see how the <code>g</code> flag works, I’ll use the <code>hatch</code> and <code>freeCodeCamp</code> examples from the previous chapter.</p>
<p>If you want to match the letters <code>h</code> in the word <code>hatch</code> with the pattern <code>h</code>, both the first and the last <code>h</code>s will be returned as matches as long as you have the <code>g</code> flag on:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/h-in-hatch-g-match.png" alt="h-in-hatch-g-match" width="600" height="400" loading="lazy"></p>
<p>And if you want to match <code>e</code> in <code>freeCodeCamp</code> with the pattern <code>e</code> and you turn on the <code>g</code> flag, the second and third <code>e</code>s are returned as a match too:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/e-in-fcc-g-match.png" alt="e-in-fcc-g-match" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-case-insensitive-flag">The <code>case-insensitive</code> Flag</h3>
<p>The <code>case insensitive</code> flag is denoted by <code>i</code>. As the name implies, it lets you perform case-insensitive matching.</p>
<p>By default, regular expressions perform case-sensitive matching. But with the <code>i</code> flag you can perform case-insensitive matching, so you won’t bother about casing in your patterns.</p>
<p>With this, uppercase or lowercase will be ignored. That means <code>Hello</code> and <code>hello</code> will be treated as the same thing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/hello-insensitive.png" alt="hello-insensitive" width="600" height="400" loading="lazy"></p>
<p><code>freeCodeCamp</code> and <code>freecodecamp</code> are treated the same, too:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/fcc-insensitive.png" alt="fcc-insensitive" width="600" height="400" loading="lazy"></p>
<p><code>RegEx</code> and <code>regex</code> are also the same thing:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regex-insensitive.png" alt="regex-insensitive" width="600" height="400" loading="lazy"></p>
<p>Another thing is that if you’re using a character class, for example <code>[a-z]</code>, it would match uppercase letters too if you turn on the <code>case-insensitive</code> flag.</p>
<p>So, the pattern <code>[a-z]</code> also matches uppercase letters with the <code>case-insensitive</code> flag turned on:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/carset-insensitive.png" alt="carset-insensitive" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-multi-line-and-single-line-flags">The <code>multi-line</code> and <code>single-line</code> Flags</h3>
<p>Denoted by <code>m</code>, the <code>multi-line</code> flag tells the regular expressions engine that the test string is more than one line. Since the <code>multi-line</code> flag influences the behavior of the start and end anchor metacharacters (<code>^</code> and <code>$</code>), you’ll learn more about it under the anchors and word boundaries chapter.</p>
<p>The <code>single-line</code> flag is denoted by <code>s</code>. Just like the <code>multi-line</code> flag, the <code>single-line</code> flag also works with a metacharacter called the wildcard (<code>.</code>).  You will see the <code>single-line</code> flag in action under the chapter for metacharacters.</p>
<h3 id="heading-the-unicode-flag">The <code>Unicode</code> Flag</h3>
<p>The Unicode flag enables full Unicode matching in the regular expressions engine that supports it. It is denoted by <code>u</code>.</p>
<p>By default, JavaScript and many other programming languages treat strings as a sequence of 16-bit code units. With the <code>u</code> flag, regex patterns can match against Unicode code points instead of code units. This allows handling characters like emojis, certain symbols, and characters from non-Latin scripts. So, when you set the flag, it modifies the behavior of certain escape sequences and metacharacters to work with regular expressions.</p>
<p>For example, the escape sequence <code>\u{1F602}</code> will match the literal character <code>u{1F602}</code> if you don’t turn on the <code>u</code> flag:
<img src="https://www.freecodecamp.org/news/content/images/2023/07/u-flag-literal-match.png" alt="u-flag-literal-match" width="600" height="400" loading="lazy"></p>
<p>But if you turn on the <code>u</code> flag, the same pattern matches the face with tears emoji:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/u-flag-emoji-match.png" alt="u-flag-emoji-match" width="600" height="400" loading="lazy"></p>
<p>That is one way to match emojis and other Unicode characters. Take the Unicode of the emoji and put the hexadecimal in curly braces, then precede the two with <code>\u</code>.</p>
<p>For instance, the Unicode of growing heart is <code>U+1F497</code>, the pattern to match it would be <code>\u{1F497}</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/growing-heart-match.png" alt="growing-heart-match" width="600" height="400" loading="lazy"></p>
<p>You will see more examples of how the flag works in the chapter on how to use regular expressions in JavaScript.</p>
<h3 id="heading-the-sticky-flag">The <code>sticky</code> Flag</h3>
<p>The sticky flag is denoted by <code>y</code>. It’s a feature of JavaScript regular expressions implemented in ECMAScript 6. The <code>y</code> flag limits matching to the current position in the string, which you can specify with the <code>lastIndex</code> property of the <code>RegExp()</code> constructor.</p>
<p>When you use the <code>y</code> flag, it uses the <code>lastIndex</code> property to determine where the next search will start. The pattern matches only if it occurs exactly at the lastIndex position or at the beginning of the string.</p>
<p>Unlike the global (<code>g</code>) flag, the <code>y</code> flag does not find all matches but stops after the first successful match.</p>
<p>In a regex engine like regex101.com, the <code>y</code> flag usually anchors to the start of the test string and stops there:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/anchor-flag-match.png" alt="anchor-flag-match" width="600" height="400" loading="lazy"></p>
<p>Since the <code>y</code> flag typically works with the <code>lastIndex</code> property of JavaScript regular expressions, we will look at more examples in the chapter on how to use regular expressions in JavaScript – specifically when we look at the <code>sticky</code> of the regular expressions constructor.</p>
<p>You can also combine multiple flags to write more complex syntax. For example, you can use the <code>g</code> flag with the <code>i</code> flag for global and case-insensitive matching:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/g-and-i-flag.png" alt="g-and-i-flag" width="600" height="400" loading="lazy"></p>
<h2 id="heading-chapter-4-how-to-use-regular-expressions-in-javascript">Chapter 4: How to Use Regular Expressions in JavaScript</h2>
<h3 id="heading-how-to-create-regular-expressions-in-javascript">How to Create Regular Expressions in JavaScript</h3>
<p>There are two ways you can create regular expressions in JavaScript. The first is with <strong>regex literal syntax</strong> and the second is with the <code>RegExp()</code> constructor.</p>
<p>To create a regular expression with the regex literal syntax, you have to enclose the pattern inside two forward slashes (<code>/</code>) like this:</p>
<pre><code class="lang-js">/regex pattern/
</code></pre>
<p>If you want to use one or more flags, it has to be after the second slash:</p>
<pre><code class="lang-js">/regex pattern/flag
</code></pre>
<p>Depending on your use case, you might have to assign the regex to a variable:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regex = <span class="hljs-regexp">/regex pattern/</span>flag
</code></pre>
<p>The flag could be any of the flags available in the JavaScript regular expressions engine.</p>
<p>If you want to create regular expressions with the <code>RegExp()</code> constructor, you have to use the <code>new</code> keyword, then put the pattern and the flag inside the <code>RegExp()</code> brackets. </p>
<p>This is what the syntax looks like:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> regex = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">"regex pattern"</span>, <span class="hljs-string">"flag"</span>);
</code></pre>
<p>Since <code>RegExp()</code> is a constructor, there are some methods and properties available in it with which you can work with regular expressions. Whether you create your pattern with the literal syntax <code>//</code> or the <code>RegExp()</code> constructor, the methods and properties are available for it.</p>
<h3 id="heading-methods-of-the-regexp-constructor">Methods of the <code>RegExp()</code> Constructor</h3>
<p>The methods of the <code>RegExp()</code> constructor are defined on the <code>RegExp.prototype</code>. You can quickly check the methods (and properties) by typing <code>RegExp().__proto__</code> and hitting <code>ENTER</code> in your browser console. These methods include <code>test()</code>, <code>exec()</code>, and <code>toString()</code>. </p>
<p>Apart from those three, some methods take regular expressions as a parameter. But it is better to discuss them under "string methods for working with regular expressions" because, at their core, they are string methods that take regular expressions as a parameter.</p>
<p>Let’s take a look at what <code>test()</code>, <code>exec()</code>, and <code>toString()</code> do.</p>
<h4 id="heading-the-test-method">The <code>test()</code> Method</h4>
<p>The <code>test()</code> method tests for a match between a regular expression and the test string and returns a boolean as the result. If there's a match, it returns <code>true</code>, and if there's no match, it returns <code>false</code>.</p>
<p>In the example below, there's a match for the pattern <code>/freeCodeCamp/</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-built_in">console</span>.log(re.test(testStr)); <span class="hljs-comment">//true</span>
</code></pre>
<p>But in the example below, there's no match for the pattern <code>/fcc/</code>, so the <code>test()</code> method returns <code>false</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/fcc/</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-built_in">console</span>.log(re.test(testStr)); <span class="hljs-comment">//false</span>
</code></pre>
<p>Apart from testing random patterns against a string, the <code>test()</code> method can be useful in form validation. </p>
<h4 id="heading-the-exec-method">The <code>exec()</code> Method</h4>
<p>The <code>exec()</code> method executes a search for a match in a test string and returns an array containing a piece of detailed information about the first match. If there's no match, it returns <code>null</code>.</p>
<p>That detailed information contains the <strong>first match</strong>, <strong>the index of the match</strong>, <strong>captured groups</strong> (if any), and the <strong>length</strong>.</p>
<p>Here's an example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-built_in">console</span>.log(re.exec(testStr));
</code></pre>
<p>And here’s a screenshot of the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exec-res.png" alt="exec-res" width="600" height="400" loading="lazy"></p>
<p>If you want to make the <code>exec()</code> method return all the matches, you can use the <code>g</code> flag on the pattern and then loop through with a <code>while</code> loop:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/g</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp is a great place to start learning to code from scratch. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-keyword">let</span> match;

<span class="hljs-keyword">while</span> ((match = re.exec(testStr)) !== <span class="hljs-literal">null</span>) {
  <span class="hljs-built_in">console</span>.log(match[<span class="hljs-number">0</span>]);
}
</code></pre>
<p>Here's what the result looks like in the console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exec-multi-res.png" alt="exec-multi-res" width="600" height="400" loading="lazy"></p>
<p>You can go further by accessing the index of the matches this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/g</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp is a great place to start learning to code from scratch. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-keyword">let</span> match;

<span class="hljs-keyword">while</span> ((match = re.exec(testStr)) !== <span class="hljs-literal">null</span>) {
  <span class="hljs-built_in">console</span>.log(match[<span class="hljs-number">0</span>]);

  <span class="hljs-comment">//   Access the indices of the matches</span>
  <span class="hljs-built_in">console</span>.log(match.index);
}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exec-indices-res.png" alt="exec-indices-res" width="600" height="400" loading="lazy"></p>
<p>If there's no match, <code>exec()</code> returns null:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/fcc/</span>;
<span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp."</span>;

<span class="hljs-built_in">console</span>.log(re.exec(testStr)); <span class="hljs-comment">//null</span>
</code></pre>
<h4 id="heading-the-tostring-method">The <code>toString()</code> Method</h4>
<p>The <code>toString()</code> method converts a regex pattern to a string. In JavaScript, the <code>toString()</code> method is in every object. Regular expressions are treated as an object behind the scenes, that's why you can create them with the <code>new</code> keyword.</p>
<p>Using this method on a regex pattern converts the pattern to a string:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pattern = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> strPattern = pattern.toString();

<span class="hljs-built_in">console</span>.log(strPattern, <span class="hljs-keyword">typeof</span> strPattern); <span class="hljs-comment">// /freeCodeCamp/ string</span>
</code></pre>
<p>Even if you create the pattern with the <code>RegExp()</code> constructor, you get the result the same way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pattern = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>);
<span class="hljs-keyword">const</span> strPattern = pattern.toString();

<span class="hljs-built_in">console</span>.log(strPattern, <span class="hljs-keyword">typeof</span> strPattern); <span class="hljs-comment">// /freeCodeCamp/ string</span>
</code></pre>
<p>And if you have a flag in the pattern, it would be returned as a part of the string:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> pattern = <span class="hljs-regexp">/freeCodeCamp/gi</span>;
<span class="hljs-keyword">const</span> strPattern = pattern.toString();

<span class="hljs-built_in">console</span>.log(strPattern, <span class="hljs-keyword">typeof</span> strPattern); <span class="hljs-comment">// /freeCodeCamp/gi string</span>
</code></pre>
<h3 id="heading-properties-of-the-regexp-constructor">Properties of the <code>RegExp()</code> Constructor</h3>
<p>The properties of the <code>RegExp()</code> constructor are defined on the <code>RegExp.prototype</code>. They include:</p>
<ul>
<li><code>RegExp.prototype.global</code></li>
<li><code>RegExp.prototype.source</code></li>
<li><code>RegExp.prototype.flags</code></li>
<li><code>RegExp.prototype.multiline</code></li>
<li><code>RegExp.prototype.ignoreCase</code></li>
<li><code>RegExp.prototype.dotAll</code></li>
<li><code>RegExp.prototype.sticky</code></li>
<li><code>RegExp.prototype.unicode</code></li>
</ul>
<p>In short, there are the <code>global</code>, <code>source</code>, <code>flags</code>, <code>multiline</code>, <code>ignoreCase</code>, <code>dotAll</code>, <code>sticky</code>, and <code>unicode</code>.</p>
<p>Most of the properties check whether a certain flag is used or not. Let's take a look at how each of the properties works. </p>
<h4 id="heading-the-global-property">The <code>global</code> Property</h4>
<p>The global property checks whether the <code>g</code> flag is used with a regex pattern or not. If the pattern has the <code>g</code> flag, it returns <code>true</code>, otherwise it returns <code>false</code>. </p>
<p>Remember the <code>global</code> (<code>g</code>) flag indicates that the regex pattern should not just return the first match but all the matches.</p>
<p>Here's how the <code>global</code> property works in code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/g</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> re3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>);
<span class="hljs-keyword">const</span> re4 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'g'</span>);

<span class="hljs-built_in">console</span>.log(re1.global); <span class="hljs-comment">//true</span>
<span class="hljs-built_in">console</span>.log(re2.global); <span class="hljs-comment">//false</span>
<span class="hljs-built_in">console</span>.log(re3.global); <span class="hljs-comment">//false</span>
<span class="hljs-built_in">console</span>.log(re4.global); <span class="hljs-comment">//true</span>
</code></pre>
<h4 id="heading-the-flag-property">The <code>flag</code> Property</h4>
<p>The flag property returns the flags you use in the regex pattern in alphabetical order. That is, <code>g</code> before <code>i</code>, <code>i</code> before <code>m</code>, <code>m</code> before <code>y</code>, and so on.</p>
<p>In the code below, you can see that the <code>g</code> flag comes before <code>i</code>, and <code>m</code> comes before <code>y</code>: </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/gi</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'my'</span>);

<span class="hljs-built_in">console</span>.log(re1.flags); <span class="hljs-comment">//gi</span>
<span class="hljs-built_in">console</span>.log(re2.flags); <span class="hljs-comment">//my</span>
</code></pre>
<h4 id="heading-the-source-property">The <code>source</code> Property</h4>
<p>The <code>source</code> property returns the regex pattern as a string. So, it acts like the <code>toString()</code> method.</p>
<p>The difference between the <code>source</code> property and the <code>toString()</code> method is that the <code>source</code> property excludes the flag you use with the pattern. Also, the <code>source</code> property does not show the literal forward slashes you use for creating the regex.</p>
<p>In the code below, you can see the forward slashes don’t get printed, the flags are omitted too, and the <code>type</code> is a string:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/gi</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'my'</span>);

<span class="hljs-keyword">const</span> re1Source = re1.source;
<span class="hljs-keyword">const</span> re2Source = re2.source;

<span class="hljs-built_in">console</span>.log(re1Source, <span class="hljs-keyword">typeof</span> re1Source); <span class="hljs-comment">// freeCodeCamp string</span>
<span class="hljs-built_in">console</span>.log(re2Source, <span class="hljs-keyword">typeof</span> re2Source); <span class="hljs-comment">// freeCodeCamp string</span>
</code></pre>
<h4 id="heading-the-multiline-property">The <code>multiline</code> Property</h4>
<p>The <code>multiline</code> flag is another boolean property of the <code>RegExp()</code> constructor. It specifies whether the <code>multiline</code> flag is used with the pattern or not by returning <code>true</code> or <code>false</code>. </p>
<p>Remember the <code>multiline</code> (<code>m</code>) flag indicates that the test string should be treated as a text that has more than one line.</p>
<p>Here's how the <code>multiline</code> property works in action:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/gi</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'my'</span>);

<span class="hljs-keyword">const</span> re1Source = re1.multiline;
<span class="hljs-keyword">const</span> re2Source = re2.multiline;

<span class="hljs-built_in">console</span>.log(re1Source); <span class="hljs-comment">//false</span>
<span class="hljs-built_in">console</span>.log(re2Source); <span class="hljs-comment">// true</span>
</code></pre>
<h4 id="heading-the-ignorecase-property">The ignoreCase Property</h4>
<p>The <code>ignoreCase</code> property specifies whether the case-insensitive flag (<code>i</code>) is used in the regex pattern. It returns <code>true</code> if you use the <code>i</code> flag and <code>false</code> if you don’t use it.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/freeCodeCamp/i</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> re3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>, <span class="hljs-string">'i'</span>);
<span class="hljs-keyword">const</span> re4 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'freeCodeCamp'</span>);

<span class="hljs-built_in">console</span>.log(re1.ignoreCase); <span class="hljs-comment">//true</span>
<span class="hljs-built_in">console</span>.log(re2.ignoreCase); <span class="hljs-comment">// false</span>
<span class="hljs-built_in">console</span>.log(re3.ignoreCase); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re4.ignoreCase); <span class="hljs-comment">// false</span>
</code></pre>
<h4 id="heading-the-unicode-property">The <code>Unicode</code> Property</h4>
<p>The <code>unicode</code> property helps you check whether the Unicode (<code>u</code>) flag is used in the regex pattern or not. If it finds the <code>u</code> flag, it returns <code>true</code>, otherwise it returns <code>false</code>.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/\u{1F1F3}\u{1F1EC}/u</span>; <span class="hljs-comment">//matches the Nigerian flag emoji</span>
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/\u{1F1F3}\u{1F1EC}/</span>;
<span class="hljs-keyword">const</span> re3 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'\u{1F1F3}\u{1F1EC}'</span>, <span class="hljs-string">'u'</span>);
<span class="hljs-keyword">const</span> re4 = <span class="hljs-keyword">new</span> <span class="hljs-built_in">RegExp</span>(<span class="hljs-string">'\u{1F1F3}\u{1F1EC}'</span>);

<span class="hljs-built_in">console</span>.log(re1.unicode); <span class="hljs-comment">//true</span>
<span class="hljs-built_in">console</span>.log(re2.unicode); <span class="hljs-comment">// false</span>
<span class="hljs-built_in">console</span>.log(re3.unicode); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re4.unicode); <span class="hljs-comment">// false</span>
</code></pre>
<h4 id="heading-the-sticky-property">The <code>sticky</code> Property</h4>
<p>The sticky property indicates whether the sticky (<code>y</code>) flag is set in the regular expression or not. Even though that's what it does, it's still a bit tricky to understand because of the <code>lastIndex</code> property.</p>
<p>When the <code>y</code> flag is set, the regex engine in use will attempt to match the pattern starting at the exact position specified by the <code>lastIndex</code> property (without using the <code>g</code> flag). If a match is found, the <code>lastIndex</code> property is updated to the position immediately after the end of the match.</p>
<p>To help you understand that better, here's a code snippet with comments:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/xyz/y</span>;
<span class="hljs-keyword">const</span> str = <span class="hljs-string">'xyzxyz'</span>;

re.lastIndex = <span class="hljs-number">0</span>;
<span class="hljs-built_in">console</span>.log(re.test(str)); <span class="hljs-comment">// true – there's a match at index 0 to 2</span>
<span class="hljs-built_in">console</span>.log(re.lastIndex); <span class="hljs-comment">// 3</span>

re.lastIndex = <span class="hljs-number">1</span>;
<span class="hljs-built_in">console</span>.log(re.test(str)); <span class="hljs-comment">// false – no match at the specified index</span>
<span class="hljs-built_in">console</span>.log(re.lastIndex); <span class="hljs-comment">// 0 – resets to 0 because there's no match at the specified index</span>

re.lastIndex = <span class="hljs-number">3</span>;
<span class="hljs-built_in">console</span>.log(re.test(str)); <span class="hljs-comment">// true – there's a match at index 3 to 5</span>
<span class="hljs-built_in">console</span>.log(re.lastIndex); <span class="hljs-comment">// 6</span>

re.lastIndex = <span class="hljs-number">6</span>;
<span class="hljs-built_in">console</span>.log(re.test(str)); <span class="hljs-comment">// false</span>
<span class="hljs-built_in">console</span>.log(re.lastIndex); <span class="hljs-comment">// 0 – resets to 0 because there's no match at the specified index</span>
</code></pre>
<p><strong>N.B.</strong>: The <code>dotAll</code> property works with the wildcard (<code>.</code>) metacharacter. Due to that, you will see how it works in detail in the chapter on metacharacters. Also, <code>hasIndices</code> works with captures. So, you will see how to use it under the chapter on grouping and capturing.</p>
<h3 id="heading-string-methods-for-working-with-regular-expressions">String Methods for Working with Regular Expressions</h3>
<p>JavaScript provides some inbuilt methods for working with strings. Some of these methods take regular expressions as a parameter. These methods include <code>match()</code>, <code>matchAll()</code>, <code>replace()</code>, <code>replaceAll()</code>, <code>split()</code>, and <code>search()</code>.</p>
<p>Let's look at each of them one by one.</p>
<h4 id="heading-the-search-method">The <code>search()</code> Method</h4>
<p>The <code>search()</code> method searches for the match of a regular expression in a string and returns the index of the match. </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">"fCC is the abbreviation for freeCodeCamp. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> searchFCC = myStr.search(re);

<span class="hljs-built_in">console</span>.log(searchFCC); <span class="hljs-comment">//28</span>
</code></pre>
<p>If the <code>search()</code> method finds no match, it returns <code>-1</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">"fCC is the abbreviation for freeCodeCamp. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/FCC/</span>;
<span class="hljs-keyword">const</span> searchFCC = myStr.search(re);

<span class="hljs-built_in">console</span>.log(searchFCC); <span class="hljs-comment">//-1</span>
</code></pre>
<p>You might be thinking using the <code>g</code> flag with the pattern would return the indices of all the matches, but this isn't the case. The <code>g</code> flag does not affect the <code>search()</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">"fCC is the abbreviation for freeCodeCamp. freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/g</span>; <span class="hljs-comment">//pattern with g flag</span>
<span class="hljs-keyword">const</span> searchFCC = myStr.search(re);

<span class="hljs-built_in">console</span>.log(searchFCC); <span class="hljs-comment">//28</span>
</code></pre>
<p>If you want to get the indices of all the matches, you should use the <code>match()</code> or <code>matchAll()</code> method.</p>
<h4 id="heading-the-match-method">The <code>match()</code> Method</h4>
<p>The <code>match()</code> method lets you specify a regex pattern as the parameter, then it runs through the string you use it against and returns an array containing the substring(s) that match the regex pattern.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str = <span class="hljs-string">'freeCodeCamp'</span>;
match = my_str.match(<span class="hljs-regexp">/free/</span>);

<span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// [ 'free', index: 0, input: 'freeCodeCamp', groups: undefined ]</span>
</code></pre>
<p>You can also separate the regex pattern into a separate variable:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str = <span class="hljs-string">'freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/</span>;
<span class="hljs-keyword">const</span> match = my_str.match(re);

<span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// [ 'free', index: 0, input: 'freeCodeCamp', groups: undefined ]</span>
</code></pre>
<p>If <code>match()</code> finds multiple matches, it returns all of them in the array, provided you use the <code>g</code> flag in the pattern: </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;
<span class="hljs-keyword">const</span> match = my_str.match(re);

<span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// ['free', 'free', 'free']</span>
</code></pre>
<p>If you expand the array, this is what it looks like:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match-method-matches.png" alt="match-method-matches" width="600" height="400" loading="lazy"></p>
<p>Since the result is an array, you should probably use <code>console.table()</code> instead of <code>console.log()</code> so you can see the indices of the matches:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;
<span class="hljs-keyword">const</span> match = my_str.match(re);

<span class="hljs-built_in">console</span>.table(match);
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match-console-table.png" alt="match-console-table" width="600" height="400" loading="lazy"></p>
<p>If the <code>match()</code> method finds no match, it returns <code>null</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str = <span class="hljs-string">'freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/ref/</span>;
<span class="hljs-keyword">const</span> match = my_str.match(re);

<span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// null</span>
</code></pre>
<h4 id="heading-the-matchall-method">The <code>matchAll()</code> Method</h4>
<p><code>matchAll()</code> is a hybrid of the <code>match()</code> method. It returns an iterator of all the substrings that match the regular expressions you provide. This means you have to use it with the <code>global</code> (<code>g</code>) flag.</p>
<p>Because it returns the iterator of all matches, <code>matchAll()</code> is a great option for looping through the matches of regular expressions. </p>
<p>An alternative to iterating through the matches of a regular expression is using the <code>exec()</code> method and <code>g</code> flag, then looping with a <code>while</code> loop this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;

<span class="hljs-keyword">let</span> match;
<span class="hljs-keyword">while</span> ((match = re.exec(my_str))) {
  <span class="hljs-built_in">console</span>.log(match[<span class="hljs-number">0</span>]); <span class="hljs-comment">//</span>
}

<span class="hljs-comment">// free</span>
<span class="hljs-comment">// free</span>
<span class="hljs-comment">// free</span>
</code></pre>
<p>With the <code>matchAll()</code> method, you don’t need the <code>exec()</code> and <code>while</code> loop. All you need is a <code>for…of</code> loop to get the matches:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;
<span class="hljs-keyword">const</span> matches = my_str.matchAll(re);

<span class="hljs-built_in">console</span>.log(matches); <span class="hljs-comment">// RegExpStringIterator {}</span>

<span class="hljs-comment">//loop through the matches with a for...of loop</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> match <span class="hljs-keyword">of</span> matches) {
  <span class="hljs-built_in">console</span>.log(match);
}
</code></pre>
<p>This returns each <code>match</code>, their index, the test string, the length, and groups in their respective arrays:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/matchAll-console.png" alt="matchAll-console" width="600" height="400" loading="lazy"></p>
<p>You can modify the console log to get only the matches and their index this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;
<span class="hljs-keyword">const</span> matches = my_str.matchAll(re);

<span class="hljs-built_in">console</span>.log(matches); <span class="hljs-comment">// RegExpStringIterator {}</span>

<span class="hljs-comment">//loop through the matches with a for...of loop</span>
<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> match <span class="hljs-keyword">of</span> matches) {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Found a match <span class="hljs-subst">${match[<span class="hljs-number">0</span>]}</span> at index <span class="hljs-subst">${match.index}</span>`</span>);
}

<span class="hljs-comment">/*
Output:
Found a match free at index 0
Found a match free at index 66
Found a match free at index 98
*/</span>
</code></pre>
<p>You can also use the <code>Array.from()</code> method to do the same thing:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> my_str =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money, that's why it's called freeCodeCamp. Learn to code for free today."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/free/g</span>;

<span class="hljs-built_in">Array</span>.from(my_str.matchAll(re), <span class="hljs-function">(<span class="hljs-params">match</span>) =&gt;</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`Found a match <span class="hljs-subst">${match[<span class="hljs-number">0</span>]}</span> at index <span class="hljs-subst">${match.index}</span>`</span>)
);

<span class="hljs-comment">/*
Output:
Found a match free at index 0
Found a match free at index 66
Found a match free at index 98
*/</span>
</code></pre>
<p>If the <code>matchAll()</code> method finds no match, it returns an empty iterator. And if you decide to loop through that empty iterator, there'll be nothing to see in the console.</p>
<h4 id="heading-the-replace-method">The <code>replace()</code> Method</h4>
<p>The <code>replace()</code> method does what its name implies. It searches for matches of a specified string or regular expression in a string and replaces them with the specified replacement string. It returns a new string with the replacements applied.</p>
<p>The <code>replace()</code> method is not as straightforward as <code>match()</code> and <code>matchAll()</code> because it accepts two parameters – a regular expression and the replacement string. Any substring of the test string that matches the regular expressions is then replaced with the replacement string.</p>
<p>If the regular expression does not include the global (<code>g</code>) flag, only the first match is replaced:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'Elephants are very large animals. They are large to the extent that they can uproot a large tree.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/large/</span>;
<span class="hljs-keyword">const</span> replaceLarge = myStr.replace(re, <span class="hljs-string">'massive'</span>);

<span class="hljs-built_in">console</span>.log(replaceLarge); <span class="hljs-comment">// Elephants are very massive animals. They are large to the extent that they can uproot a large tree.</span>
</code></pre>
<p>If you use the <code>g</code> flag in the pattern, all the matches are replaced:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'Elephants are very large animals. They are large to the extent that they can uproot a large tree.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/large/g</span>;
<span class="hljs-keyword">const</span> replaceLarge = myStr.replace(re, <span class="hljs-string">'massive'</span>);

<span class="hljs-built_in">console</span>.log(replaceLarge); <span class="hljs-comment">// Elephants are very massive animals. They are massive to the extent that they can uproot a massive tree.</span>
</code></pre>
<h4 id="heading-the-replaceall-method">The <code>replaceAll()</code> Method</h4>
<p>The <code>replaceAll()</code> method is relatively new because it became available in ECMAScript 2021. It is a hybrid of <code>replace()</code>.</p>
<p>Both <code>replace()</code> and <code>replaceAll()</code> do the same thing by taking a regular expression and a replacement string as parameters, and replacing all matches with the specified replacement string. </p>
<p>But unlike <code>replace()</code> which will only replace the first match if you don’t use the <code>g</code> flag, <code>replaceAll()</code> replaces all the matches by default:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'Elephants are very large animals. They are large to the extent that they can uproot a large tree.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/large/g</span>;
<span class="hljs-keyword">const</span> replaceLarge = myStr.replaceAll(re, <span class="hljs-string">'massive'</span>);

<span class="hljs-built_in">console</span>.log(replaceLarge); <span class="hljs-comment">// Elephants are very massive animals. They are massive to the extent that they can uproot a massive tree.</span>
</code></pre>
<p>If you don’t use the <code>g</code> flag with <code>replaceAll()</code>, it throws a <code>TypeError</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'Elephants are very large animals. They are large to the extent that they can uproot a large tree.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/large/</span>;
<span class="hljs-keyword">const</span> replaceLarge = myStr.replaceAll(re, <span class="hljs-string">'massive'</span>);

<span class="hljs-built_in">console</span>.log(replaceLarge); <span class="hljs-comment">// Uncaught TypeError: String.prototype.replaceAll called with a non-global RegExp argument</span>
<span class="hljs-comment">//    at String.replaceAll (&lt;anonymous&gt;)</span>
</code></pre>
<h4 id="heading-the-split-method">The <code>split()</code> Method</h4>
<p>The <code>split()</code> method takes a string or regex and splits the string you use it against into an array based on the string or regex you pass into it. The <code>split()</code> method also takes an optional <code>limit</code> parameter, a positive number. When you specify the <code>limit</code>, the splitting stops at that limit.</p>
<p>Wherever the <code>split()</code> finds a match, it creates a new item in the array. Here's how it works:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">"Codes don't lie. You're the one doing something wrong."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\s/</span>; <span class="hljs-comment">// "\s" means white space - spacebar, backspace, tab, ENTER.</span>

<span class="hljs-keyword">const</span> splitedStr = myStr.split(re);
<span class="hljs-built_in">console</span>.log(splitedStr);

<span class="hljs-comment">/* 
Output:
[
  'Codes',  "don't",
  'lie.',   "You're",
  'the',    'one',
  'doing',  'something',
  'wrong.'
]
*/</span>
</code></pre>
<p>Here's how to use the <code>split()</code> method with the <code>limit</code> parameter:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">"Codes don't lie. You're the one doing something wrong."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\s/</span>; <span class="hljs-comment">// "\s" means white space - spacebar, backspace, tab, ENTER.</span>

<span class="hljs-keyword">const</span> splitedStr = myStr.split(re, <span class="hljs-number">5</span>); <span class="hljs-comment">// 5 is the limit here</span>
<span class="hljs-built_in">console</span>.log(splitedStr);

<span class="hljs-comment">/*
output: [ 'Codes', "don't", 'lie.', "You're", 'the' ]
*/</span>
</code></pre>
<h3 id="heading-how-to-match-literal-characters-in-javascript-regular-expressions">How to Match Literal Characters in JavaScript Regular Expressions</h3>
<p>As I pointed out earlier, literal characters are texts or strings you will write patterns for as they are.</p>
<p>If you want to match the text <code>hello</code>, <code>/hello/</code> should be your pattern. You can then use the <code>i</code> flag with it to match both <code>hello</code> and <code>Hello</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testString = <span class="hljs-string">'hello'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/hello/</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/hello/i</span>;

<span class="hljs-built_in">console</span>.log(re.test(testString)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re2.test(testString)); <span class="hljs-comment">// true</span>
</code></pre>
<p>If you want to match <code>freeCodeCamp</code>, the pattern should be just that. You can also create a pattern that matches <code>freeCodeCamp</code> in any case:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testString = <span class="hljs-string">'freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/freeCodeCamp/</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/freeCodeCamp/i</span>; <span class="hljs-comment">// match freeCodeCamp in any case</span>

<span class="hljs-built_in">console</span>.log(re.test(testString)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re2.test(testString)); <span class="hljs-comment">// true</span>
</code></pre>
<p>You can also match digits using literal characters:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> num = <span class="hljs-number">10234</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/2/</span>;

<span class="hljs-built_in">console</span>.log(re.test(num)); <span class="hljs-comment">//true</span>
</code></pre>
<h3 id="heading-how-to-use-character-sets-in-javascript-regular-expressions">How to Use Character Sets in JavaScript Regular Expressions</h3>
<p>As a reminder, a character set is a group of characters enclosed in square brackets. They provide a way to specify a set of characters from which the regex engine can match a single character at a specific position in a test string. </p>
<p>Character sets allow you to specify a range of characters, individual characters, or a combination of both.</p>
<p>Here are common examples of popular character sets in regular expressions:</p>
<ul>
<li><code>[abc]</code>: matches either <code>a</code>, <code>b</code>, or <code>c</code></li>
<li><code>[aeiou]</code>: matches any vowel character</li>
<li><code>[a-z]</code>: matches any lowercase letter from <code>a</code> to <code>z</code></li>
<li><code>[A-Z]</code>: matches any uppercase letter from <code>A</code> to <code>Z</code></li>
<li><code>[0-9]</code>: matches any digit from 0 to 9</li>
</ul>
<p>Let's look at how to match each of the above character sets in JavaScript regular expressions:</p>
<pre><code class="lang-js"><span class="hljs-comment">// uppercase character set</span>
<span class="hljs-keyword">const</span> hcaseRe = <span class="hljs-regexp">/[A-Z]/</span>;
<span class="hljs-keyword">const</span> hcaseStr = <span class="hljs-string">'freeCodeCamp is cool'</span>;

<span class="hljs-built_in">console</span>.log(hcaseRe.test(hcaseStr)); <span class="hljs-comment">//true</span>

<span class="hljs-comment">// vowels character set</span>
<span class="hljs-keyword">const</span> vowelsRe = <span class="hljs-regexp">/[aeiou]/</span>;
<span class="hljs-keyword">const</span> vowelsStr = <span class="hljs-string">'Imagine how pronunciation would have been without vowels'</span>;

<span class="hljs-built_in">console</span>.log(vowelsRe.test(vowelsStr)); <span class="hljs-comment">//true</span>

<span class="hljs-comment">// [abc] character set</span>
<span class="hljs-keyword">const</span> abcSetRe = <span class="hljs-regexp">/[abc]/</span>;
<span class="hljs-keyword">const</span> abcSetStr = <span class="hljs-string">'freeCodeCamp is totally free'</span>;

<span class="hljs-built_in">console</span>.log(abcSetRe.test(abcSetStr)); <span class="hljs-comment">//true</span>

<span class="hljs-comment">// number character set</span>
<span class="hljs-keyword">const</span> numRe = <span class="hljs-regexp">/[0-9]/</span>;
<span class="hljs-keyword">const</span> numStr = <span class="hljs-string">'Thank God for Arabic numerals 0 to 9.'</span>;

<span class="hljs-built_in">console</span>.log(numRe.test(numStr)); <span class="hljs-comment">//true</span>
</code></pre>
<h2 id="heading-chapter-5-metacharacters-quantifiers-repeated-matches-and-optional-matches">Chapter 5: Metacharacters, Quantifiers, Repeated Matches, and Optional Matches</h2>
<h3 id="heading-what-are-metacharacters">What are Metacharacters?</h3>
<p>In regular expressions, metacharacters are characters that have special meanings beyond their literal meaning. </p>
<p>Metacharacters are the backbone of regular expressions. They serve as the building blocks for constructing better regex patterns and defining the behavior of the regular expression engine you're using, but with an extra learning curve.</p>
<p>This part of the book is where you will learn about topics such as:</p>
<ul>
<li>Anchors</li>
<li>Word boundaries</li>
<li>How to specify character ranges</li>
<li>How to match every occurrence with the wildcard</li>
<li>Alternation</li>
<li>Greediness and laziness of regular expressions and how to prevent greediness</li>
</ul>
<p>And lots more.</p>
<p>If you want to match any metacharacter as a literal character, you have to escape it with a backslash (<code>\</code>). And if there's a metacharacter represented by a word, you have to escape it with the backslash too. So, the backslash is also a separate metacharacter.</p>
<p>There's a metacharacter to negate most metacharacters. For instance, <code>\b</code> and <code>\s</code> represent the word boundary and space metacharacters. If you want to negate them, you can use <code>\B</code> and <code>\S</code> respectively. That's the pattern most metacharacters follow – the small letter is the metacharacter and the capital letter negates it.</p>
<p>Metacharacters are categorized into single and double metacharacters. As the name implies, single metacharacters have a "single" character and double metacharacters have a "double" character. </p>
<p>Most metacharacters are also called shorthand character classes. As we look at each metacharacter, you will see whether it is a single or double metacharacter.</p>
<h3 id="heading-the-word-and-non-word-metacharacters">The Word and Non-word Metacharacters</h3>
<p>Represented by <code>\w</code>, the word metacharacter is a shorthand character class that matches all word characters. Word characters are alphanumeric characters and underscores. So, they are <code>a-z</code>, A-Z, <code>0-9</code>, and underscore (<code>_</code>).</p>
<p>Here's what happens when you use <code>\w</code> in a regex tester:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/w-matches.png" alt="w-matches" width="600" height="400" loading="lazy"></p>
<p>And here’s how it works in JavaScript:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Every alphanumeric character (a to z and 0 to 9) and underscore (_) is a word character'</span>;
<span class="hljs-keyword">const</span> wordCharacterRe = <span class="hljs-regexp">/\w/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(wordCharacterRe));
</code></pre>
<p>Since word characters are alphanumeric characters and underscores, you can simulate the <code>\w</code> metacharacter by putting all the examples in a character set:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Every alphanumeric character (a to z and 0 to 9) and underscore (_) is a word character'</span>;
<span class="hljs-keyword">const</span> wordCharacterRe = <span class="hljs-regexp">/[a-z A-Z 0-9_]/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(wordCharacterRe));
</code></pre>
<p>The non-word metacharacter is the opposite of the word metacharacter and it is represented by an escaped capital letter W (<code>\W</code>). </p>
<p>The non-word metacharacter matches every other character apart from alphanumeric characters and the underscore. That includes spaces, punctuation marks, and symbols:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/w-matches-1.png" alt="w-matches-1" width="600" height="400" loading="lazy"></p>
<p>Here it is in action in some JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Every character apart from alphanumeric characters (a to z and 0 to 9) and underscore (_) is a non-word character'</span>;
<span class="hljs-keyword">const</span> nonWordCharacterRe = <span class="hljs-regexp">/\W/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(nonWordCharacterRe));
</code></pre>
<p>Since you can represent the word metacharacter by putting all the characters in a character set, you may be wondering how you can do the same for the non-word metacharacter. </p>
<p>That's where the negated character set comes in. The caret (<code>^</code>) is used for negation. It is one of the two <strong>anchor metacharacters</strong>, which we'll look at next.</p>
<h3 id="heading-the-anchor-metacharacters">The Anchor Metacharacters</h3>
<p>Caret (<code>^</code>) and dollar sign (<code>$</code>) are the two anchor metacharacters. They are both single metacharacters.</p>
<p>The caret anchors the regex pattern to the start of a line or string, so you can call it a "start of line anchor". </p>
<p>For example, if you want to match the text "freeCodeCamp" and you want to make sure it's at the start of the line or a string, you can use the caret this way:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/fcc-anchor-match.png" alt="fcc-anchor-match" width="600" height="400" loading="lazy"></p>
<p>If the <code>freeCodeCamp</code> text is not at the start of the line, there won't be a match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/fcc-anchor-no-match.png" alt="fcc-anchor-no-match" width="600" height="400" loading="lazy"></p>
<p>Here are the two cases in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"freeCodeCamp doesn't charge you any money. That's why it's called freeCodeCamp because. Learn to code for free today."</span>; <span class="hljs-comment">// has "freeCodeCamp" at the start of the line</span>

<span class="hljs-keyword">const</span> testStr2 =
  <span class="hljs-string">"It's called freeCodeCamp because freeCodeCamp doesn't charge you any money. Learn to code for free today."</span>; <span class="hljs-comment">// does not have "freeCodeCamp" at the start of the line</span>

<span class="hljs-keyword">const</span> startAnchorRe = <span class="hljs-regexp">/^freeCodeCamp/</span>;

<span class="hljs-built_in">console</span>.log(startAnchorRe.test(testStr)); <span class="hljs-comment">//true</span>
<span class="hljs-built_in">console</span>.log(startAnchorRe.test(testStr2)); <span class="hljs-comment">//false</span>
</code></pre>
<p>The dollar sign metacharacter is the opposite of the caret. It anchors the regex pattern to the end of the line or string. So, there will only be a match if the target text is at the end of the line.</p>
<p>To use the <code>$</code> metacharacter, it has to be the last character in your pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-meta-match.png" alt="dollar-meta-match" width="600" height="400" loading="lazy"></p>
<p>If the target string has more than one line and the target text is at the end of each line, the last one matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-last-match.png" alt="dollar-last-match" width="600" height="400" loading="lazy"></p>
<p>To correct this behavior, you have to use both the <code>g</code> and <code>m</code> flags:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-multiple-match.png" alt="dollar-multiple-match" width="600" height="400" loading="lazy"></p>
<p>Here are all the cases in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"The lion is not the king of the jungle because of its strength, the lion is the king of the jungle because it's never intimidated"</span>;

<span class="hljs-keyword">const</span> testStr2 = <span class="hljs-string">`The lion is not the king of the jungle because of its strength, the lion is the king of the jungle because it's never intimidated

This is another line that ends with intimidated

And this is the last line that ends with intimidated

And this is the last line that ends with intimidated`</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/intimidated$/</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/intimidated$/gm</span>;

<span class="hljs-built_in">console</span>.log(re.test(testStr)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(testStr2)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re2.test(testStr2)); <span class="hljs-comment">// true</span>
</code></pre>
<p>If the target text is not at the end of the line, there won't be any match:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">"A lion can never be intimidated because it's the king of the jungle"</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/intimidated$/</span>;

<span class="hljs-built_in">console</span>.log(re.test(testStr)); <span class="hljs-comment">// false</span>
</code></pre>
<p>When you use both the dollar and caret metacharacters with the <code>g</code> and <code>m</code> flags, they don’t just match at the start and end of a line, they find the matches at the start and end of each line:</p>
<pre><code class="lang-js"><span class="hljs-comment">//dollar with g and m flags</span>
<span class="hljs-keyword">const</span> testStr1 = <span class="hljs-string">`The lion is not the king of the jungle because of its strength, the lion is the king of the jungle because it's never intimidated

Another line with intimidated

And another line with intimidated`</span>;

<span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/intimidated$/gm</span>;
<span class="hljs-keyword">const</span> matches1 = testStr1.match(re1);

<span class="hljs-built_in">console</span>.log(matches1); <span class="hljs-comment">// [ 'intimidated', 'intimidated', 'intimidated' ]</span>

<span class="hljs-comment">// caret with g and m flags</span>
<span class="hljs-keyword">const</span> testStr = <span class="hljs-string">`freeCodeCamp doesn't charge you any money. That's why it's called freeCodeCamp because. Learn to code for free today.

freeCodeCamp starts this line

freeCodeCamp starts this line too
`</span>;

<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/^freeCodeCamp/gm</span>;
<span class="hljs-keyword">const</span> matches2 = testStr.match(re2);

<span class="hljs-built_in">console</span>.log(matches2); <span class="hljs-comment">// [ 'freeCodeCamp', 'freeCodeCamp', 'freeCodeCamp' ]</span>
</code></pre>
<p>As I pointed out earlier, the caret metacharacter is typically used for negating a character set or any other character. With that, you tell the regex engine in use not to match that character or each of the character sets.</p>
<p>For example, if you have the pattern <code>[^a]</code>, then all letters "a" in the test string won't be returned as matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/unmatch-As.png" alt="unmatch-As" width="600" height="400" loading="lazy"></p>
<p>If you have the pattern <code>[^aeiou]</code>, all the vowels in the test string won't be returned as matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/unmatch-vowels.png" alt="unmatch-vowels" width="600" height="400" loading="lazy"></p>
<p>If you have the pattern <code>[^a-zA-Z0-9_]</code>, that's equivalent to the non-word metacharacter (<code>\W</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/non-word-char-class.png" alt="non-word-char-class" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-digit-and-non-digit-metacharacters">The Digit and Non-digit Metacharacters</h3>
<p>The digit metacharacter is represented by <code>\d</code>. You can negate it with <code>\D</code>, so <code>\D</code> is the non-digit metacharacter.</p>
<p><code>\d</code> matches all numbers (0 to 9), so it is a shorthand character class for <code>[0-9]</code>. So, if you have a string and you want to extract the numbers from it, you can use the <code>\d</code> metacharacter. But you have to use it with the <code>g</code> flag so it matches every number in the test string:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/Screenshot-2023-07-25-at-12.27.21.png" alt="Screenshot-2023-07-25-at-12.27.21" width="600" height="400" loading="lazy"></p>
<p>You can use the <code>match()</code> method to extract the numbers in JavaScript too:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Arabic numerals are 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. From those ten numbers, you can write any number you want, including nonillion and decillion.'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(re));

<span class="hljs-comment">/* output
[
  '0', '1', '2', '3',
  '4', '5', '6', '7',
  '8', '9'
]
*/</span>
</code></pre>
<p>A more straightforward example is matching dates since dates are mostly in numbers. For example, if you want to match a date in the format <code>dd/mm/yyyy</code>, you can match it with the pattern <code>/\d\d\/\d\d\/\d\d\d\d/</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> date = <span class="hljs-string">'22/04/2023'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d\d\/\d\d\/\d\d\d\d/</span>;

<span class="hljs-built_in">console</span>.log(re.test(date)); <span class="hljs-comment">// true</span>
</code></pre>
<p>Since you can also have a period or hyphen as the separator of a date, you can account for those too by putting all the possible separators in a character set:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> slashSeparatedSate = <span class="hljs-string">'22/04/2023'</span>;
<span class="hljs-keyword">const</span> hyphenSeparatedDate = <span class="hljs-string">'22-04-2023'</span>;
<span class="hljs-keyword">const</span> periodSeparatedDate = <span class="hljs-string">'22.04.2023'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d\d[/.-]\d\d[/.-]\d\d\d\d/</span>;

<span class="hljs-built_in">console</span>.log(re.test(slashSeparatedSate)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(hyphenSeparatedDate)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(periodSeparatedDate)); <span class="hljs-comment">// true</span>
</code></pre>
<p><strong>N.B.</strong>: The pattern above matches a date but also an invalid date like <code>99/45/2022</code>. A better way to match dates is provided in the applications of the regex chapter.</p>
<p>Another example is matching phone numbers. For example, US phone numbers are in the format <code>(123) 456-7890</code>. You can use the pattern <code>/\(\d\d\d\) \d\d\d-\d\d\d\d/</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> USPhone = <span class="hljs-string">'(123) 456-7890'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\(\d\d\d\) \d\d\d-\d\d\d\d/</span>;

<span class="hljs-built_in">console</span>.log(re.test(USPhone)); <span class="hljs-comment">// true</span>
</code></pre>
<p>The non-digit metacharacter is the opposite of the digit metacharacter. It matches all non-digit characters. That is, alphabets, spaces, and symbols. In other words, it is the shorthand character class for <code>[^0-9]</code>.</p>
<p>If you want to extract all non-digit characters in a string, you can use the <code>\D</code> metacharacter:
<img src="https://www.freecodecamp.org/news/content/images/2023/07/D-matches.png" alt="D-matches" width="600" height="400" loading="lazy"></p>
<p>This is it in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'Arabic numerals are 0, 1, 2, 3, 4, 5, 6, 7, 8, and 9. From those ten numbers, you can write any number you want, including nonillion and decillion.'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\D/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(re));

<span class="hljs-comment">/* output
A total of 137 matches is too much to show here, but you can test it out yourself.
*/</span>
</code></pre>
<h3 id="heading-the-square-brackets-metacharacter">The Square Brackets Metacharacter</h3>
<p>You've already seen the square brackets (<code>[]</code>) metacharacter in action. Square brackets are used for specifying a character class, or character set. And if you want to match them as a literal character, then you have to escape them.</p>
<p>One thing to have in mind is that some metacharacters lose their meanings inside the character set. The exceptions to this are:</p>
<ul>
<li>The caret (<code>^</code>) which you can use to negate a character set</li>
<li>The hyphen (<code>-</code>) which you can use to specify ranges</li>
</ul>
<p><strong>N.B.</strong>: Sometimes, you might encounter a situation where you have to escape some metacharacters inside a character set.</p>
<p>If you want to match any of those characters in a character set, you have to escape it. If you are just passing the three of those characters in directly, you don't need to escape them if the caret is not the first character.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> testStr =
  <span class="hljs-string">'If you want to match the caret (^), hyphen and (-) symbols in a character set, you might not have to escape them.'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/[-^]/g</span>;

<span class="hljs-built_in">console</span>.log(testStr.match(re)); <span class="hljs-comment">// [ '^', '-' ]</span>
</code></pre>
<p>But if the caret is the first character in the character set alongside some word and non-word character, you should escape it, otherwise it will negate all other characters:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/unescaped-caret.png" alt="unescaped-caret" width="600" height="400" loading="lazy"></p>
<h3 id="heading-the-word-boundary-and-non-word-boundary-metacharacters">The Word Boundary and Non-word Boundary Metacharacters</h3>
<p>The word boundary metacharacter is represented by <code>\b</code> and the non-word boundary metacharacter is represented by <code>\B</code>. Both let you match a specific part of a string where a word character and a non-word character exist.</p>
<p>Word boundary (<code>\b</code>) matches a position between a word character (<code>\w</code>) and a non-word character (<code>\W</code>), and vice versa. It can be useful when you want to match a certain word in a string, or if you want to make sure a particular word or character is in a string.</p>
<p>Here's an example in a regex tester:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/b-match.png" alt="b-match" width="600" height="400" loading="lazy"></p>
<p>And the same example in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'A Tiger can do everything a lion does, apart from being a family man.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\blion\b/</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re));

<span class="hljs-comment">/*
Output:
[
  'lion',
  index: 28,
  input: 'A Tiger can do everything a lion does, apart from being a family man.',
  groups: undefined
]
*/</span>
</code></pre>
<p>If you use a <code>g</code> flag with the pattern and use the <code>match()</code> method, all the matches will be returned – as expected:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'A Tiger can do everything a lion does, apart from being a family man. Not even a tiger can intimidate a lion within his family.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\blion\b/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'lion', 'lion' ]</span>
</code></pre>
<p>On the other hand, the non-word boundary (<code>\B</code>) is the opposite of the word boundary (<code>\b</code>). So, it matches everywhere a word boundary won't return a match. For example, "thin" in "everything":</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/thing-everything.png" alt="thing-everything" width="600" height="400" loading="lazy"></p>
<p>And also "code" in "freeCodeCamp" when you use the case insensitive (<code>i</code>) flag:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/code-freeCodeCamp.png" alt="code-freeCodeCamp" width="600" height="400" loading="lazy"></p>
<p>You can see that the first "code" in the text wasn't the match returned. That's the power of word and non-word boundary metacharacters.</p>
<p>Here's what the two reveal in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr1 =
  <span class="hljs-string">'A Tiger can do everything a lion does, apart from being a family man.'</span>;
<span class="hljs-keyword">const</span> myStr2 = <span class="hljs-string">'Learn to code for free on freeCodeCamp.'</span>;

<span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/\Bthin\B/</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/\Bcode\B/i</span>;

<span class="hljs-built_in">console</span>.log(myStr1.match(re1));
<span class="hljs-built_in">console</span>.log(myStr2.match(re2));

<span class="hljs-comment">/*
Output:
[
  'thin',
  index: 20,
  input: 'A Tiger can do everything a lion does, apart from being a family man.',
  groups: undefined
]
[
  'Code',
  index: 30,
  input: 'Learn to code for free on freeCodeCamp.',
  groups: undefined
]
*/</span>
</code></pre>
<h3 id="heading-the-parenthesis-metacharacter">The Parenthesis Metacharacter</h3>
<p>The parenthesis metacharacters (<code>(</code> and <code>)</code>) let you create grouping and capturing. With them, you can treat any group of characters as a single unit and apply a common modifier or quantifier to them. </p>
<p>Parenthesis is also used for creating both lookahead and lookbehind assertions.</p>
<p>When you create the group and assertions, you can reference them later in the same pattern with a backslash and the order in which they appear. For example, you can reference the first group by specifying <code>\1</code> in the pattern.</p>
<p>In this book, a whole chapter is dedicated to grouping and capturing. There, you will learn more about grouping and capturing so you can see the parenthesis metacharacters in action.</p>
<h3 id="heading-the-space-and-non-space-metacharacters">The Space and Non-space Metacharacters</h3>
<p>It is impossible for text to make sense without spaces. Not just a "space", but also other space characters like tabs, carriage returns, and new lines. This is why the space and non-space metacharacters are made available in regular expressions.</p>
<p>The space metacharacter is represented by <code>\s</code> and the non-space metacharacter is represented by <code>\S</code>.</p>
<p><code>\s</code> matches all space characters:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/s-match.png" alt="s-match" width="600" height="400" loading="lazy"></p>
<p>And <code>\S</code> matches all non-space metacharacters:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/S-matches.png" alt="S-matches" width="600" height="400" loading="lazy"></p>
<p>Here's how both the <code>\s</code> and <code>\S</code> metacharacters work in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'Learn to code for free on freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> spaceRe = <span class="hljs-regexp">/\s/g</span>;
<span class="hljs-keyword">const</span> nonSpaceRe = <span class="hljs-regexp">/\S/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(spaceRe)); <span class="hljs-comment">// [' ', ' ', ' ', ' ', ' ', ' '];</span>

<span class="hljs-built_in">console</span>.log(myStr.match(nonSpaceRe)); 
<span class="hljs-comment">// [</span>
<span class="hljs-comment">// 'L', 'e', 'a', 'r', 'n', 't',</span>
<span class="hljs-comment">// 'o', 'c', 'o', 'd', 'e', 'f',</span>
<span class="hljs-comment">// 'o', 'r', 'f', 'r', 'e', 'e',</span>
<span class="hljs-comment">// 'o', 'n', 'f', 'r', 'e', 'e',</span>
<span class="hljs-comment">// 'C', 'o', 'd', 'e', 'C', 'a',</span>
<span class="hljs-comment">// 'm', 'p'</span>
<span class="hljs-comment">// ]</span>
</code></pre>
<p>One cool thing you can do with <code>\s</code> in JavaScript is to replace all spaces with say, a hyphen, or any other thing you want:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'Learn to code for free on freeCodeCamp'</span>;
<span class="hljs-keyword">const</span> replaceHyphen = myStr.replace(spaceRe, <span class="hljs-string">'-'</span>);

<span class="hljs-built_in">console</span>.log(replaceHyphen); <span class="hljs-comment">// Learn-to-code-for-free-on-freeCodeCamp</span>
</code></pre>
<p>The space metacharacter does not just match the spacebar you press on the keyboard of your device. It also matches:</p>
<ul>
<li>A tab character</li>
<li>A carriage return character</li>
<li>A new line character</li>
<li>A vertical tab character</li>
<li>And a form feed character</li>
</ul>
<p>Here's an example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/s-match-all.png" alt="s-match-all" width="600" height="400" loading="lazy"></p>
<p>You can't see the match for the carriage return but it's there:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/s-match-all-view-1.png" alt="s-match-all-view-1" width="600" height="400" loading="lazy"></p>
<p>If you want to match each of those space characters, they also have their unique metacharacters:</p>
<ul>
<li><code>\t</code> for tab</li>
<li><code>\r</code> for carriage return</li>
<li><code>\n</code> for new line</li>
<li><code>\v</code> for vertical tab</li>
<li><code>\f</code> for form feed.</li>
</ul>
<p>You should be aware that most of the time, <code>\s</code> is all you need because it can do the matching for any space character.</p>
<h3 id="heading-the-pipe-metacharacter">The Pipe Metacharacter</h3>
<p>Also known as the <code>OR</code> operator, the pipe metacharacter is represented by the pipe symbol (<code>|</code>). It lets you specify multiple alternatives for matching. </p>
<p>The pipe matches the character preceding it, or the character that follows it. For example, if you have <code>website|web\sapp</code> as your pattern, then one or both of <code>website</code> and <code>web app</code> will be returned as the match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/web-webapp-alt.png" alt="web-webapp-alt" width="600" height="400" loading="lazy"></p>
<p>The evaluation goes from left to right. If a match is found on the left, it returns the match. And if there's no match on the left, the character on the right-hand side is evaluated for a possible match. If both characters on the left and right are in the test string, then both are returned as matches.</p>
<p>You can also have more than two characters separated by the pipe symbols. For instance, the pattern <code>/o|a|i|re/</code> would match <code>o</code>, <code>a</code>, <code>i</code>, and <code>re</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-o-i-alt-match.png" alt="a-o-i-alt-match" width="600" height="400" loading="lazy"></p>
<p>There's no limit to the characters you can separate with it.</p>
<p>You can see I used the <code>g</code> flag in those examples. If you don’t use the <code>g</code> flag and both the left and right characters are matches, only the first match in the test string will be returned:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/first-occur-i-o-a.png" alt="first-occur-i-o-a" width="600" height="400" loading="lazy"></p>
<p>Here's a clearer example:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/clearer-alt.png" alt="clearer-alt" width="600" height="400" loading="lazy"></p>
<p>Here's how using the <code>OR</code> operator works with the <code>g</code> flag in code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The website and web app are running fine'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/website|web\sapp/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// returns [ 'website', 'web app' ] because of the g flag</span>
</code></pre>
<p>And here's how it works without the <code>g</code> flag:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The website and web app are running fine'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/website|web\sapp/</span>;

<span class="hljs-keyword">const</span> matches = myStr.match(re);

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> match <span class="hljs-keyword">of</span> matches) {
  <span class="hljs-built_in">console</span>.log(match); <span class="hljs-comment">// returns "website" and ignores web app because there's no g flag</span>
}
</code></pre>
<h3 id="heading-how-to-match-repeated-characters-with-quantifiers">How to Match Repeated Characters With Quantifiers</h3>
<p>Repeated characters occur when the same character exists in multiple numbers consecutively.</p>
<p>When you have a repeated character in your test string, you don't need to repeat a particular character in your pattern to match it. That's because there are metacharacters available for <strong>one or more matches</strong>, <strong>zero or more matches</strong>, and <strong>zero or one matches</strong>, AKA <strong>optional matches</strong>.</p>
<h4 id="heading-one-or-more-matches-with-the-addition-sign-metacharacter">One or More Matches with the Addition Sign Metacharacter</h4>
<p>As you can guess, the addition sign metacharacter is represented with a plus (<code>+</code>). You can also call it the "one or more quantifier".</p>
<p>If you want a particular character to be repeated one or many times, that's what the addition sign metacharacter does. </p>
<p>For example, the pattern, <code>/fe+d/</code> will match any word with one letter <code>e</code> or multiple letters <code>e</code> that occur consecutively. For instance, <code>fed</code> and <code>feed</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/one-or-more-e.png" alt="one-or-more-e" width="600" height="400" loading="lazy"></p>
<p>A practical example in JavaScript is extracting vowels in a test string while limiting occurrences by making sure multiple vowels that follow one another are also returned:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'You should plant trees to save mother earth'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/[aeiou]+/gi</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re));

<span class="hljs-comment">/*
Output:
[
  'ou', 'ou', 'a',
  'ee', 'o',  'a',
  'e',  'o',  'e',
  'ea'
]
*/</span>
</code></pre>
<p>You can also append the addition sign metacharacter to other metacharacters. For example, /\d+/ would match one or more digits:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/d--matches.png" alt="d--matches" width="600" height="400" loading="lazy"></p>
<p>You can also add the <code>+</code> metacharacter to a character set to repeat it one or more times. In the screenshot below, the pattern <code>/f[a-z]+/</code> would match one or more letter <code>f</code> followed by any set of small letters:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/f-set-zero-or-more.png" alt="f-set-zero-or-more" width="600" height="400" loading="lazy"></p>
<h4 id="heading-zero-or-more-matches-with-the-asterisk-metacharacter">Zero or More Matches with the Asterisk Metacharacter</h4>
<p>The asterisk metacharacter (<code>*</code>) matches zero or many occurrences of the character it comes after. You can also call it a "zero or more quantifier". </p>
<p>So, if you want a character to be repeated zero or more than one time, you can use the asterisk metacharacter. A basic example is using the pattern <code>/go*d/</code> would match any word that starts with the letter <code>g</code> followed by any number of the letter <code>o</code>, and ending with the letter <code>d</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/gd-zero-or-more.png" alt="gd-zero-or-more" width="600" height="400" loading="lazy"></p>
<p>Just like you can do with the plus metacharacter, you can also append the asterisk metacharacter to any other metacharacter. For example, you can match empty strings with the pattern <code>/\s*/</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match-empty-string.png" alt="match-empty-string" width="600" height="400" loading="lazy"></p>
<p>Doubting that? Here it is in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\s*/</span>;
<span class="hljs-keyword">const</span> emptyString = <span class="hljs-string">''</span>;

<span class="hljs-built_in">console</span>.log(re.test(emptyString)); <span class="hljs-comment">// true</span>
</code></pre>
<p>I didn’t know matching empty strings was as straightforward as this until I got to this point in the book!</p>
<p>Again, like the plus metacharacter, you can also add the <code>*</code> metacharacter to a character set to repeat it zero or more times:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/f-set-one-or-more.png" alt="f-set-one-or-more" width="600" height="400" loading="lazy"></p>
<p>Here's the same thing in JavaScript code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'You can make yourself free from diseases'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/f[a-z]*/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'f', 'free', 'from' ]</span>
</code></pre>
<p>You can see the <code>f</code> in the word <code>yourself</code> is even a match too. That's one way to deduce that the asterisk (<code>*</code>) returns more matches than the addition sign (<code>+</code>) metacharacter because it is greedier. You will learn about greediness of a regular expression in the closing part of this chapter.</p>
<h4 id="heading-zero-or-one-matches-with-the-question-mark-metacharacter">Zero or One Matches with the Question Mark Metacharacter</h4>
<p>The question mark metacharacter (<code>?</code>) is also known as the zero or one quantifier. It lets you make the character that precedes it optional, so it plays an important role in preventing greediness.</p>
<p>For example, the pattern <code>/ab?c/</code> will match <code>abc</code> and <code>ac</code>, but never <code>abbbc</code> or any other numbers of <code>b</code> between the <code>a</code> and <code>c</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/abc-optional.png" alt="abc-optional" width="600" height="400" loading="lazy"></p>
<p>This is not the case with the other two metacharacters for matching repeated characters (<code>+</code> and <code>*</code>). The pattern <code>/ab*c/</code> will match all of  <code>abc</code>, <code>ac</code>, <code>abbbc</code>, and <code>abbbbbbbc</code> while <code>/ab+c/</code> will leave out <code>ac</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'abc ac abbbc abbbbbbbc'</span>;
<span class="hljs-keyword">const</span> re1 = <span class="hljs-regexp">/ab*c/g</span>;
<span class="hljs-keyword">const</span> re2 = <span class="hljs-regexp">/ab+c/g</span>;
<span class="hljs-keyword">const</span> re3 = <span class="hljs-regexp">/ab?c/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re1)); <span class="hljs-comment">// [ 'abc', 'ac', 'abbbc', 'abbbbbbbc' ]</span>
<span class="hljs-built_in">console</span>.log(myStr.match(re2)); <span class="hljs-comment">// [ 'abc', 'abbbc', 'abbbbbbbc' ]</span>
<span class="hljs-built_in">console</span>.log(myStr.match(re3)); <span class="hljs-comment">// [ 'abc', 'ac' ]</span>
</code></pre>
<p>A better example is tailoring a regex pattern to match words that have different spellings due to the small variations in British and American English. For example, <code>color</code> and <code>colour</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/colou-r-optional.png" alt="colou-r-optional" width="600" height="400" loading="lazy"></p>
<p>There's also <code>centre</code> and <code>center</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/cente-re--optional.png" alt="cente-re--optional" width="600" height="400" loading="lazy"></p>
<p>You can extract those words in JavaScript. You can't use the <code>match()</code> method for that because it causes some unexpected behaviors when used with the <code>?</code> metacharacter.</p>
<p>Here's how I was able to do it for <code>color</code> and <code>colour</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The words center and centre are homophones'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/cente?re?/g</span>;

<span class="hljs-keyword">let</span> match;
<span class="hljs-keyword">const</span> matches = [];

<span class="hljs-keyword">while</span> ((match = re.exec(myStr)) !== <span class="hljs-literal">null</span>) {
  matches.push(match[<span class="hljs-number">0</span>]);
}

<span class="hljs-built_in">console</span>.log(matches); <span class="hljs-comment">// ["center", "centre"]</span>
</code></pre>
<p>I used the same approach to extract <code>center</code> and <code>centre</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'It is "colour" in British English and "color" in American English'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/colou?r/g</span>;

<span class="hljs-keyword">let</span> match;
<span class="hljs-keyword">const</span> matches = [];

<span class="hljs-keyword">while</span> ((match = re.exec(myStr)) !== <span class="hljs-literal">null</span>) {
  matches.push(match[<span class="hljs-number">0</span>]);
}

<span class="hljs-built_in">console</span>.log(matches); <span class="hljs-comment">// [ 'colour', 'color' ]</span>
</code></pre>
<p>Many times, it's challenging knowing which to use for character repetition between these three metacharacters – <code>*</code>, <code>+</code>, and <code>?</code>. It can even be hard to get used to what each of them does if you're just starting out with regular expressions.</p>
<p>Be aware that identifying them and knowing which to use between them is not a herculean task. Here are some things to note about the three of them:</p>
<ul>
<li>Asterisk (<code>*</code>) means "zero or many": use it if you want a character not to appear in the target string or you want the same character to be more than one</li>
<li>Plus (<code>+</code>) means "one or many": use it if you want a character to appear once or more than once in the target string</li>
<li>Question mark (<code>?</code>) means "zero or one": use it if you want a character to be optional in the target string.</li>
</ul>
<h3 id="heading-how-to-specify-match-quantity-with-the-curly-braces-metacharacter">How to Specify Match Quantity with the Curly Braces Metacharacter</h3>
<p>Quantifiers let you indicate the quantity or frequency of a preceding character in a pattern with curly braces (<code>{}</code>}. With those braces, you can specify an exact quantifier, a minimum quantifier, and a range quantifier.</p>
<h4 id="heading-the-range-quantifier">The Range Quantifier</h4>
<p>The general syntax for the range quantifier looks like this:</p>
<pre><code class="lang-console">char{n1,n2}
</code></pre>
<ul>
<li><code>cha</code> is any character you're applying the quantifier to</li>
<li><code>n1</code> is the minimum number of times you want the character to repeat</li>
<li><code>n2</code> is the maximum number of times you want the character to repeat</li>
</ul>
<p>An example is the pattern <code>/a{3,6}/</code>. This means you want to match between three and six letters <code>a</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-3-6--match.png" alt="a-3-6--match" width="600" height="400" loading="lazy"></p>
<p>If you have more than six letters <code>a</code> in the test string, the first six will match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-range-error.png" alt="a-range-error" width="600" height="400" loading="lazy"></p>
<p>To fix this, you can surround the pattern in a word boundary:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-range-error-fix.png" alt="a-range-error-fix" width="600" height="400" loading="lazy"></p>
<p>You can also attach the range quantifier to metacharacters. For example, you can extract any number that is at least in hundreds this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'The marathon had 500 participants, with 251 finishing under 3 hours, and the winner crossed the line at 4800 seconds.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\b\d{3,6}\b/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ '500', '251', '4800' ]</span>
</code></pre>
<h4 id="heading-the-minimum-quantifier">The Minimum Quantifier</h4>
<p>The minimum quantifier lets you specify the minimum number of times you want the character that precedes it to match. You can do this by putting a comma right after the number in the curly brace. The general syntax looks like this: <code>{n,}</code>. </p>
<p>For example, the pattern <code>/a{3,}/</code> means you want a minimum of three letters <code>a</code>. In this case, one letter <code>a</code> and two letters <code>a</code> won't be a match, but three letters <code>a</code> and upward would be returned as matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/a-3---match.png" alt="a-3---match" width="600" height="400" loading="lazy"></p>
<p>Let's extract those matches with the <code>match()</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'"a" won\'t match here. "aa" won\'t match too, but "aaa" is a match, "aaaa" is also a match, and every other number of "a"'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/a{3,}/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'aaa', 'aaaa' ]</span>
</code></pre>
<h4 id="heading-the-exact-quantifier">The Exact Quantifier</h4>
<p>The exact specifier is represented by <code>{n}</code>. In this case, <code>n</code> stands for the exact number of times you want that character to be repeated. For instance, the pattern, <code>/a{3}/</code> means you want <code>a</code> to be repeated three times</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exact-a-3-.png" alt="exact-a-3-" width="600" height="400" loading="lazy"></p>
<p>Unfortunately, a match is returned anywhere there are three letters <code>a</code> that follow one another. You can prevent this behavior with word boundary (<code>\b</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exact-a-3--fixed-.png" alt="exact-a-3--fixed-" width="600" height="400" loading="lazy"></p>
<p>That way, you can extract the abbreviations, <code>AAA</code> from a string using the <code>match()</code> method. Below is an example: </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">"There is American automobile association (AAA)and there is Australian automobile association (AAA). What I've never seen is AAAA or AAAAAA."</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\ba{3}\b/gi</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'AAA', 'AAA' ]</span>
</code></pre>
<p>Remember the pattern I wrote to match dates in the <code>dd/mm/yyyy</code> format? You can make it better and easier to read with the exact quantifier like this:</p>
<pre><code class="lang-console">\d{2}[/.-]\d{2}[/.-]\d{4}
</code></pre>
<p>Everything still works fine:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> slashSeparatedSate = <span class="hljs-string">'22/04/2023'</span>;
<span class="hljs-keyword">const</span> hyphenSeparatedDate = <span class="hljs-string">'22-04-2023'</span>;
<span class="hljs-keyword">const</span> periodSeparatedDate = <span class="hljs-string">'22.04.2023'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d{2}[/.-]\d{2}[/.-]\d{4}/</span>;

<span class="hljs-built_in">console</span>.log(re.test(slashSeparatedSate)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(hyphenSeparatedDate)); <span class="hljs-comment">// true</span>
<span class="hljs-built_in">console</span>.log(re.test(periodSeparatedDate)); <span class="hljs-comment">// true</span>
</code></pre>
<p>You can also make the pattern that matches the US phone number better and shorter with the same approach:</p>
<pre><code class="lang-console">\(\d{3}\) \d{3}-\d{4}
</code></pre>
<p>Everything still works fine too:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> USPhone = <span class="hljs-string">'(123) 456-7890'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\(\d{3}\) \d{3}-\d{4}/</span>;

<span class="hljs-built_in">console</span>.log(re.test(USPhone)); <span class="hljs-comment">// true</span>
</code></pre>
<h3 id="heading-the-wildcard-metacharacter">The Wildcard Metacharacter</h3>
<p>The wildcard metacharacter is represented by a dot (<code>.</code>), so you can also call it the dot metacharacter. </p>
<p>The wildcard lets you match any character apart from a new line (<code>\n</code>). That means you can use it to match alphanumeric characters, spaces, and symbols.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/wcard-match.png" alt="wcard-match" width="600" height="400" loading="lazy"></p>
<p>You can also attach the wildcard metacharacter to another metacharacter. For example, the pattern <code>/\d./g</code> should match at least a number and everything that follows it:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/digit-greedy.png" alt="digit-greedy" width="600" height="400" loading="lazy"></p>
<p>You can see that the pattern is transcending beyond the digits by matching the spaces after them. This is what is called <strong>greediness</strong>.</p>
<p>The pattern, <code>/\d.*/g</code> is even more greedy because it will match everything after it encounters the first number:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/super-digit-greedy.png" alt="super-digit-greedy" width="600" height="400" loading="lazy"></p>
<p>It’s the same in code:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'An example of a two-digit number is 20. 100 is a three-digit number. 300 and 900 are also three-digit numbers.'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\d.*/g</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ '20. 100 is a three-digit number. 300 and 900 are also three-digit numbers.']</span>
</code></pre>
<p>If you want the wildcard to match a new line too, you can use the <code>s</code> flag. Here's an example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> codeBlock = <span class="hljs-string">`
  function add(x, y) {
    /* This is a function
    that takes two numbers
    and adds them together. */
    return x + y;
  }
`</span>;

<span class="hljs-keyword">let</span> commentRegex = <span class="hljs-regexp">/\/\*(.*)\*\//</span>s; <span class="hljs-comment">// gets everything between /* and */</span>

<span class="hljs-keyword">const</span> match = codeBlock.match(commentRegex);
<span class="hljs-built_in">console</span>.log(match);
</code></pre>
<p>Here's the result:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dotAllRes-1.png" alt="dotAllRes-1" width="600" height="400" loading="lazy"></p>
<p>You can use the <code>dotAll</code> property to check if the <code>s</code> flag is used in the pattern:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> codeBlock = <span class="hljs-string">`
  function add(x, y) {
    /* This is a function
    that takes two numbers
    and adds them together. */
    return x + y;
  }
`</span>;

<span class="hljs-keyword">let</span> commentRegex = <span class="hljs-regexp">/\/\*(.*)\*\//</span>s; <span class="hljs-comment">// gets everything between /* and */</span>
<span class="hljs-keyword">const</span> match = codeBlock.match(commentRegex);

<span class="hljs-built_in">console</span>.log(commentRegex.dotAll) <span class="hljs-comment">// true;</span>
</code></pre>
<p>You can extract the match with an if statement:</p>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> codeBlock = <span class="hljs-string">`
  function add(x, y) {
    /* This is a function
    that takes two numbers
    and adds them together. */
    return x + y;
  }
`</span>;

<span class="hljs-keyword">let</span> commentRegex = <span class="hljs-regexp">/\/\*(.*)\*\//</span>s; <span class="hljs-comment">// gets everything between /* and */</span>

<span class="hljs-keyword">const</span> match = codeBlock.match(commentRegex);

<span class="hljs-keyword">if</span> (match) {
  <span class="hljs-built_in">console</span>.log(match[<span class="hljs-number">1</span>]);
}

<span class="hljs-comment">/*
Output:  
This is a function
    that takes two numbers
    and adds them together.
*/</span>
</code></pre>
<p>Because the wildcard always matches any character it encounters apart from a new line, it is better not to use it unless it is absolutely necessary. For every character the wildcard matches, there is always another way to match it.</p>
<h3 id="heading-greediness-and-laziness-in-regular-expressions">Greediness and Laziness in Regular Expressions</h3>
<p>By default, regular expression patterns are greedy, meaning they always try to match as many as possible characters. But the concept of greediness is primarily applicable to quantifiers (<code>*</code>, <code>+</code>, <code>?</code>, and <code>{}</code>) and the wildcard (<code>.</code>).</p>
<p>For Example, the pattern <code>/f.*h/gi</code> will match as many characters as possible after encountering an <code>f</code> in the target string:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/asterisk-greedy.png" alt="asterisk-greedy" width="600" height="400" loading="lazy"></p>
<p>Same for the pattern, <code>/f.*h/gi</code>:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/plus-greedy.png" alt="plus-greedy" width="600" height="400" loading="lazy"></p>
<p>It’s the same in code: </p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The fresh fish was caught in the Finnish lake'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/f.*h/gi</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'fresh fish was caught in the Finnish' ]</span>
</code></pre>
<p><strong>Laziness</strong> is the opposite of greediness and it’s the way you stop greediness. On many occasions, if you want to stop greediness, all you need is to apply the <strong>zero or ones quantifier</strong> (<code>?</code>) to the metacharacter causing the greediness.</p>
<p>Here's how I stopped the greediness of the asterisk metacharacter:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/make-asterisk-lazy.png" alt="make-asterisk-lazy" width="600" height="400" loading="lazy"></p>
<p>I stopped it for the plus metacharacter the same way:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/make-plus-lazy.png" alt="make-plus-lazy" width="600" height="400" loading="lazy"></p>
<p>I can now safely extract every word that starts with <code>f</code> and ends with <code>h</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr = <span class="hljs-string">'The fresh fish was caught in the Finnish lake'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/f.*?h/gi</span>;

<span class="hljs-built_in">console</span>.log(myStr.match(re)); <span class="hljs-comment">// [ 'fresh', 'fish', 'Finnish' ]</span>
</code></pre>
<h2 id="heading-chapter-6-grouping-and-capturing-in-regex">Chapter 6: Grouping and Capturing in Regex</h2>
<h3 id="heading-what-is-grouping">What is Grouping?</h3>
<p>Grouping means treating a regex pattern or a part of a regex pattern as a single unit. To achieve grouping, you surround the pattern or the part of the pattern you want to group in parenthesis (<code>(</code> and <code>)</code>).</p>
<p>After you've grouped the part of the pattern you want to, you can then refer back to it through a process we call "backreferencing" in regular expressions.</p>
<p>The groups you define in a pattern refer to the target string or text and not the pattern itself. You'll see this in action when it's time to discuss backreferencing. </p>
<p>After grouping, you can then apply a quantifier to that group since all the patterns in it are a unit.</p>
<p>Let's say you have a group of the ids <code>z8g4g4 ga1v4g f4k7f9 bb3b2b d6b4t5 d4cm3d e9f5y6 ggj64 mgtyqg m0foh9</code> and you want to find out which of them follow the pattern <code>letter number letter number letter number</code>. The pattern <code>[a-z]\d[a-z]\d[a-z]\d</code> can do that for you:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/without-grouping.png" alt="without-grouping" width="600" height="400" loading="lazy"></p>
<p>Using grouping, you can make the pattern shorter by grouping the <code>[a-z]\d</code> sequence and applying an exact quantifier of <code>3</code> to it:</p>
<pre><code class="lang-console">([a-z]\d){3}
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/with-grouping.png" alt="with-grouping" width="600" height="400" loading="lazy"></p>
<p>When you use grouping in a pattern, especially if you have multiple groups in the same pattern, you can use the <code>exec()</code> method to extract each of the groups.</p>
<p>A good example to illustrate this is a date in any acceptable format, for example <code>dd/mm/yyyy</code>.</p>
<p>Here's how I group the pattern <code>\d\d[/.-]\d\d[/.-]\d\d\d\d</code> into <code>dd</code>, <code>mm</code>, and <code>yyyy</code>:</p>
<pre><code class="lang-console">(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)
</code></pre>
<p>I used the <code>exec()</code> method this way:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> execRes = re.exec(date);
<span class="hljs-built_in">console</span>.log(execRes);
</code></pre>
<p>This is what the result looks like in the console:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/exec-group-res.png" alt="exec-group-res" width="600" height="400" loading="lazy"></p>
<p>In the array, you can see that:</p>
<ul>
<li>there is the whole date in the index <code>0</code></li>
<li>the index <code>1</code> has the <code>day</code></li>
<li>the index <code>2</code> has the month`</li>
<li>and the index <code>3</code> has the <code>year</code></li>
</ul>
<p>You can then use array referencing to get all of those figures:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> execRes = re.exec(date);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The full date is <span class="hljs-subst">${execRes[<span class="hljs-number">0</span>]}</span>`</span>); <span class="hljs-comment">// The full date is 22-03-2023</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The day is <span class="hljs-subst">${execRes[<span class="hljs-number">1</span>]}</span>`</span>); <span class="hljs-comment">// The day is 22</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The month is <span class="hljs-subst">${execRes[<span class="hljs-number">2</span>]}</span>`</span>); <span class="hljs-comment">// The month is 03</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The year is <span class="hljs-subst">${execRes[<span class="hljs-number">3</span>]}</span>`</span>); <span class="hljs-comment">// The year is 2023</span>
</code></pre>
<p>You can also use this approach to extract a username and domain from an email:</p>
<pre><code class="lang-js"><span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">extractUsernameAndDomain</span>(<span class="hljs-params">email</span>) </span>{
  <span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/([a-z]{2,})@([a-z]{3,}\.com)/</span>;
  <span class="hljs-keyword">const</span> result = re.exec(email);

  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The username is <span class="hljs-subst">${result[<span class="hljs-number">1</span>]}</span>`</span>);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The domain is <span class="hljs-subst">${result[<span class="hljs-number">2</span>]}</span>`</span>);
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The full email is <span class="hljs-subst">${result[<span class="hljs-number">0</span>]}</span>`</span>);
}

extractUsernameAndDomain(<span class="hljs-string">'janedoe@gmail.com'</span>);

<span class="hljs-comment">/*
Output:
The username is janedoe
The domain is gmail.com
The full email is janedoe@gmail.com
*/</span>
</code></pre>
<p>This behavior of grouping in which each match of the pattern is separated in an array according to the groups is the reason groups are also called "capturing" groups. This way, you don’t need the <code>split()</code> method of JavaScript or any other programming hacks to get each of the groups on those dates.</p>
<h3 id="heading-how-to-reference-captured-groups-with-backreferences">How to Reference Captured Groups with Backreferences</h3>
<p>Since groups are captured by default, you can refer back to them. To do this, you use a backslash (<code>\</code>) and then the order of the group in the pattern. For example, you can reference the first group with <code>\1</code> and the third group with <code>\3</code>. No zero indentation.</p>
<p>Let's say you want to match "tsetse" fly in the text <code>There are many tsetse flies in the tropics</code>. If you group the text "tse" first and use the <code>g</code> flag, you'll get two matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/tse-group-warn.png" alt="tse-group-warn" width="600" height="400" loading="lazy"></p>
<p>You can refer back to that <code>tse</code> group with <code>\1</code> and you'll have a single match: </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/tse-group-right.png" alt="tse-group-right" width="600" height="400" loading="lazy"></p>
<p>It's very important to note that when you use a capturing group, the grouping refers to the target string (or text) and not the pattern itself. The reason why the pattern <code>/(tse)\1/</code> returns a match in the last example is because of the "tse" in the text and not the "tse" in the pattern.</p>
<p>To illustrate this, let's use a date again, since the month or date and the separators can repeat and can be different. I will use the pattern <code>(\d\d)([/.-])\1\2(\d\d\d\d)</code> for matching dates that I grouped in one of the previous examples. Remember the pattern successfully matches a date:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/date-match-group.png" alt="date-match-group" width="600" height="400" loading="lazy"></p>
<p>I can group the separator too and refer back to it for the second separator. I can also refer back to the day part of the date to match the month, since they both look for two digits. </p>
<p>Here's the new pattern now:</p>
<pre><code class="lang-console">(\d\d)([/.-])\1\2(\d\d\d\d)
</code></pre>
<p>I can make the pattern shorter with an exact quantifier:</p>
<pre><code class="lang-console">(\d{2})([/.-])\1\2(\d{4})
</code></pre>
<p>The new pattern successfully matches the same date:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/date-match-group-same.png" alt="date-match-group-same" width="600" height="400" loading="lazy"></p>
<p>But the reason there's a match in the example above is that the separators are the same and the day and month are the same.</p>
<p>If the day is different from the month, there won't be a match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/no-match-because-of-day-month-difference.png" alt="no-match-because-of-day-month-difference" width="600" height="400" loading="lazy"></p>
<p>If the separators are different too, there also won't be a match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/no-match-because-of-separator-difference.png" alt="no-match-because-of-separator-difference" width="600" height="400" loading="lazy"></p>
<p>But remember that if both are the same, there will be a match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/date-match-group-same-1.png" alt="date-match-group-same-1" width="600" height="400" loading="lazy"></p>
<p>That is the reason why the groups in a pattern refer to the target string (or text) and not the pattern itself. </p>
<p>It is also possible to make a group non-capturing. That way, you won't be able to refer to it in the pattern. To create a <strong>non-capturing</strong> group, you use a question mark and a colon right after the opening parenthesis.</p>
<p>The syntax for that looks like this:</p>
<pre><code class="lang-console">(?: chars)
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/no-match-non-capture.png" alt="no-match-non-capture" width="600" height="400" loading="lazy"></p>
<p>Because of this, the text does not match the pattern anymore. To make it match again I have to:</p>
<ul>
<li>remove the first backreference (<code>\1</code>)</li>
<li>define <code>\d{2}</code> for the date</li>
<li>change the reference to the separator from <code>\2</code> to <code>\1</code></li>
</ul>
<p>Here’s the new pattern:</p>
<pre><code class="lang-console">(?:\d{2})([/.-])\d{2}\1(\d{4})
</code></pre>
<p>And now the date matches the pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/match-non-capture.png" alt="match-non-capture" width="600" height="400" loading="lazy"></p>
<h3 id="heading-how-to-use-the-d-flag-and-hasindices-property-with-groups">How to Use the <code>d</code> Flag and <code>hasIndices</code> Property with Groups</h3>
<p>The <code>d</code> flag adds index information to match objects for capture groups. This way, you won't just know what was matched by each capture group, but also where that match was found in the input string.</p>
<p>Let's look at how this works with the grouping for matching dates:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>d;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> match = re.exec(date);
<span class="hljs-built_in">console</span>.log(match);
</code></pre>
<p>The result contains an array of objects detailing the total position of all matches, and the position of each match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dFlagRes.png" alt="dFlagRes" width="600" height="400" loading="lazy"></p>
<p>If you want to see those indices, you can use <code>.indices</code> to see them:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>d;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> match = re.exec(date);

<span class="hljs-built_in">console</span>.log(match.indices);
</code></pre>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dFlagHasIndicesRes.png" alt="dFlagHasIndicesRes" width="600" height="400" loading="lazy"></p>
<p>You can also extract those indices separately:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>d;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-keyword">const</span> match = re.exec(date);

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The full index range is <span class="hljs-subst">${match.indices[<span class="hljs-number">0</span>]}</span>`</span>); <span class="hljs-comment">//The full index range is 0,10</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The day index range is <span class="hljs-subst">${match.indices[<span class="hljs-number">1</span>]}</span>`</span>); <span class="hljs-comment">// The day index range is 0,2</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The month index range is <span class="hljs-subst">${match.indices[<span class="hljs-number">2</span>]}</span>`</span>); <span class="hljs-comment">// The month index range is 3,5</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`The year index range is <span class="hljs-subst">${match.indices[<span class="hljs-number">3</span>]}</span>`</span>); <span class="hljs-comment">// The year index range is 6,10</span>
</code></pre>
<p>And finally, you can check if the <code>d</code> flag is really used with the <code>hasIndices</code> property:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(\d\d)[/.-](\d\d)[/.-](\d\d\d\d)/</span>d;
<span class="hljs-keyword">const</span> date = <span class="hljs-string">'22-03-2023'</span>;

<span class="hljs-built_in">console</span>.log(re.hasIndices); <span class="hljs-comment">// true</span>
</code></pre>
<h2 id="heading-chapter-7-lookaround-groups-lookaheads-and-lookbehinds">Chapter 7: Lookaround Groups: Lookaheads and Lookbehinds</h2>
<h3 id="heading-what-are-lookaround-groups">What are Lookaround Groups?</h3>
<p>Lookaround assertions are non-capturing groups that return matches only if the target string is followed or preceded by a particular character. </p>
<p>Lookaround assertions do not consume the characters in the input string or text. This makes them a "zero-width assertion", and that's why lookaround groups are also called "lookahead assertions".</p>
<p>There are two types of lookaround groups: <strong>lookahead</strong> and <strong>lookbehind</strong>. The two also have their positive and negative forms, so there are <strong>positive lookahead</strong>, <strong>negative lookahead</strong>, <strong>positive lookbehind</strong>, and <strong>negative lookbehind</strong> groups.</p>
<h3 id="heading-what-is-a-lookahead-group">What is a Lookahead Group?</h3>
<p>A lookahead group is a non-capturing group that lets you match a part of a string only if it is followed by another character in the string, without including that string or text to match in the pattern.</p>
<p>A lookahead group is useful when you want to match a string based on a condition. So, look at it like an <code>if</code> statement in a programming language.</p>
<p>There are two types of lookaheads, namely <strong>positive lookahead</strong> and <strong>negative lookahead</strong>.</p>
<p>Because you're still dealing with groupings, a positive lookahead is specified by an opening parenthesis followed by a question mark, an equal sign, the characters, and a closing parenthesis:</p>
<pre><code class="lang-console">(?=chars)
</code></pre>
<p>For example, the pattern <code>x(?=y)</code> means match <code>x</code> only if it is followed by <code>y</code>.</p>
<p>In the syntax of negative lookahead, you replace the equal sign with an exclamation mark:</p>
<pre><code class="lang-console">(?!chars)
</code></pre>
<p>For example, the pattern <code>x(?!y)</code> means do not match <code>x</code> if it is followed by <code>y</code>.</p>
<p>Let's look at an example of a positive lookahead assertion.</p>
<p>Say you want to match the domain name of domains that have only the <code>.org</code> extension within a string of domains with other extensions. This pattern would do it:</p>
<pre><code class="lang-console">[a-zA-Z]+(?=\.org)
</code></pre>
<p>In the pattern, <code>[a-zA-Z]+</code> represents one or more word characters, and <code>(?=\.org)</code> checks whether the domain contains a <code>.org</code> extension.</p>
<p>In the screenshot below, you can see that domain names that have a <code>.org</code> extension were matched:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/org-matches.png" alt="org-matches" width="600" height="400" loading="lazy"></p>
<p>You also can see that the words "freeCodeCamp" and "catholic" were not included in the pattern, but they still matched the pattern because they have the <code>.org</code> extension.</p>
<p>If there are no domains with the <code>.org</code> extension in the target string, there won't be any match. That's true for the domains without the <code>.org</code> extension.</p>
<p>That way, you can extract text like that in JavaScript and do whatever you want with it:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> domains = <span class="hljs-string">'koladechris.com freeCodeCamp.org mdn.com catholic.org'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/[a-zA-Z]+(?=\.org)/g</span>;

<span class="hljs-keyword">const</span> charityWebsitesArr = domains.match(re);
<span class="hljs-keyword">const</span> charityWebsites = charityWebsitesArr.join(<span class="hljs-string">','</span>).replace(<span class="hljs-regexp">/,/</span>, <span class="hljs-string">' and '</span>);

<span class="hljs-built_in">console</span>.log(charityWebsites, <span class="hljs-string">'are examples of charity organizations.'</span>); <span class="hljs-comment">//freeCodeCamp and catholic are examples of charity organizations.</span>
</code></pre>
<p>If you want to match the <code>.org</code> as well so the whole domain gets matched, you have to include the <code>.org</code> in the pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/org-all-match.png" alt="org-all-match" width="600" height="400" loading="lazy"></p>
<p>Since lookahead groups don’t consume characters, you will see a lot of developers use positive lookaheads to validate passwords.</p>
<p>Let's say you want the password to be at least six characters that includes a lowercase letter, an uppercase letter, a number, and a symbol. You can use lookaheads to define all of those conditions:</p>
<ul>
<li><code>(?=.{6,})</code> ¬– at least 6 characters</li>
<li><code>(?=.*[a-z])</code> – at least one lowercase character, but check if there are zero or many characters before it</li>
<li><code>(?=.*[A-Z])</code> – at least one lowercase character, but check if there are zero or many characters before it</li>
<li><code>(?=.*[0-9])</code> – at least one number, but check if there are zero or many characters before it</li>
<li><code>(?=.*[!@#$%%^&amp;*()+=-])</code> – accepted symbols, but check if there are zero or many characters before each</li>
<li><code>.*</code> – check if there are zero or many characters after the groups</li>
</ul>
<p>Here's the full regular expression:</p>
<pre><code class="lang-js">(?=.{<span class="hljs-number">6</span>,})(?=.*[a-z])(?=.*[A-Z])(?=.*[<span class="hljs-number">0</span><span class="hljs-number">-9</span>])(?=.*[!@#$%%^&amp;*()+=-]).*
</code></pre>
<p>And here is what matches the pattern and what does not:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/pword-lookahead.png" alt="pword-lookahead" width="600" height="400" loading="lazy"></p>
<p>To use that pattern in JavaScript, you can test it against a password string and do something from there:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> password = <span class="hljs-string">'Tse23*'</span>;
<span class="hljs-keyword">const</span> passwordRe =
  <span class="hljs-regexp">/(?=.{6,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$%%^&amp;*()+=-]).*/</span>;

<span class="hljs-keyword">if</span> (passwordRe.test(password)) {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Welcome to your dashboard!'</span>);
} <span class="hljs-keyword">else</span> {
  <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">'Incorrect password!'</span>);
}

<span class="hljs-comment">/**
output: Welcome to your dashboard!
*/</span>
</code></pre>
<p>For the application of negative lookahead, it is useful when you don't want a certain character before the character(s) you are looking for in a string. </p>
<p>Let's say you want to extract all items of an array that do not have the article "the" before them. In that case, you can use the pattern below:</p>
<pre><code class="lang-console">/^(?!.*\bThe\b).*$/
</code></pre>
<p>In the pattern above:</p>
<ul>
<li><code>^</code> ensures the regex pattern matches from the start of the line</li>
<li><code>(?!.*\bThe\b)</code> is the negative lookbehind that ensures that the article "the" is not in the target string</li>
<li><code>\bThe\b</code> is a word boundary that matches "The" and nothing else</li>
<li><code>.*</code> the wildcard that matches any character apart from a new line</li>
</ul>
<pre><code class="lang-js"><span class="hljs-keyword">let</span> docTitles = [
  <span class="hljs-string">'The Incredible Dr. Poll'</span>,
  <span class="hljs-string">'Born in Africa'</span>,
  <span class="hljs-string">"America's Funniest Home Videos"</span>,
  <span class="hljs-string">'The Lion Queen'</span>,
  <span class="hljs-string">'Snake in the City'</span>,
];
<span class="hljs-keyword">let</span> re = <span class="hljs-regexp">/^(?!.*\bThe\b).*$/</span>;

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">let</span> title <span class="hljs-keyword">of</span> docTitles) {
  <span class="hljs-keyword">if</span> (re.test(title)) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`A Title without "The": <span class="hljs-subst">${title}</span>`</span>);
  }
}

<span class="hljs-comment">/*
Output:
A Title without "The": Born in Africa
A Title without "The": America's funniest home videos
A Title without "The": Snake in the City
*/</span>
</code></pre>
<h3 id="heading-what-is-a-lookbehind-group">What is a Lookbehind Group?</h3>
<p>A lookbehind group is similar to lookahead group. But instead of checking if a certain character(s) follows what you're trying to match, it checks whether the character(s) precedes what you're trying to match.</p>
<p>So, a lookbehind group is a non-capturing group that lets you match a part of a string only if it is preceded by another character in the string, without including that string or text to match in the pattern.</p>
<p>Like lookaheads, there are also positive and negative lookbehind assertions. A positive lookbehind returns a match only if the character you want to match is preceded by another character you specify in your pattern. On the other hand, a negative lookbehind returns a match only if the character you want to match is not preceded by another character.</p>
<p>A positive lookbehind is represented by an opening parenthesis, a question mark, a less than symbol, an equals sign, the character(s), and a closing parenthesis:</p>
<pre><code class="lang-console">(?&lt;=chars)
</code></pre>
<p>For example, the pattern <code>(?&lt;=x)y</code> indicates you want to match <code>y</code> only if there's <code>x</code> before it. In this case, <code>xx</code> or <code>yx</code> won't match, but <code>xy</code> would match.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/positive-lookbehind-match.png" alt="positive-lookbehind-match" width="600" height="400" loading="lazy"></p>
<p>For a negative lookbehind, an exclamation mark replaces the equals sign:</p>
<pre><code class="lang-console">(?&lt;!chars)
</code></pre>
<p>For example, the pattern <code>(?&lt;!x)y</code> means do not match <code>y</code> if there's <code>x</code> before it. In this case <code>by</code> would match, <code>my</code>, would match, but never <code>xy</code>.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/negative-lkb-match.png" alt="negative-lkb-match" width="600" height="400" loading="lazy"></p>
<p>Positive lookbehind groups can be useful for matching numbers preceded only by a certain currency symbol, for example numbers preceded by the dollar sign.</p>
<p>The regex pattern below has a positive lookbehind that matches a number only if it is preceded by a dollar sign:</p>
<pre><code class="lang-js">(?&lt;=\$)\d+(\.\d*)?
</code></pre>
<p>In the pattern above, the lookbehind (<code>(?&lt;=\$)</code>) checks whether there's a dollar sign before one or more digits (represented by <code>\d+</code>). The other group, <code>(\.\d*)</code>, and the zero or one quantifier (<code>?</code>) check whether the number contains floating points.</p>
<p>Here's what matches and what does not:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/positive-lkb-match.png" alt="positive-lkb-match" width="600" height="400" loading="lazy"></p>
<p>In JavaScript, what you can do with the numbers that match is to calculate the total with the <code>reduce()</code> method:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myStr =
  <span class="hljs-string">'10 pieces of the items cost $102.99, but you can get 15 for a discount of $2, and 20 for a discount of $3.99'</span>;

<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/(?&lt;=\$)\d+(\.\d*)?/g</span>;

<span class="hljs-comment">// put all the prices in an array</span>
<span class="hljs-keyword">const</span> allPrices = myStr.match(re); <span class="hljs-comment">// [ '102.99', '2', '3.99' ]</span>

<span class="hljs-comment">// convert each of the prices to a number with map() and unary plus</span>
<span class="hljs-keyword">const</span> allPricesToNum = allPrices.map(<span class="hljs-function">(<span class="hljs-params">price</span>) =&gt;</span> +price); <span class="hljs-comment">// [ 102.99, 2, 3.99 ]</span>

<span class="hljs-comment">// add all the numbers with reduce()</span>
<span class="hljs-keyword">const</span> sumOfAllPrices = allPricesToNum.reduce(<span class="hljs-function">(<span class="hljs-params">acc, curr</span>) =&gt;</span> acc + curr, <span class="hljs-number">0</span>); <span class="hljs-comment">// 108.97999999999999</span>

<span class="hljs-comment">// add a dolar sign to the number and use toFixed() to round it down</span>
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">`$<span class="hljs-subst">${sumOfAllPrices.toFixed(<span class="hljs-number">2</span>)}</span>`</span>); <span class="hljs-comment">// $108.98</span>
</code></pre>
<p>For the example of negative lookbehind, let's say you want to match a digit as long as it is not preceded by the dollar sign. This pattern does it:</p>
<pre><code class="lang-js">(?&lt;!\$)\d+
</code></pre>
<p>But unfortunately, it still looks out for a number inside another number and matches it even if there's a dollar sign before the whole number:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-negative-lkb-err.png" alt="dollar-negative-lkb-err" width="600" height="400" loading="lazy"></p>
<p>To correct that behavior, you can surround the whole pattern with a word boundary (<code>\b</code>):</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/dollar-negative-lkb-fix.png" alt="dollar-negative-lkb-fix" width="600" height="400" loading="lazy"></p>
<p>Negative lookbehind groups are supported in JavaScript as well:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> monies = <span class="hljs-string">'$123 456 $789 £12 ₦568 $8903 £345'</span>;
<span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\b(?&lt;!\$)\d+\b/g</span>;

<span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Monies without dollar sign:'</span>, monies.match(re)); <span class="hljs-comment">// Monies without dollar sign: [ '456', '12', '568', '345' ]</span>
</code></pre>
<h2 id="heading-chapter-8-regex-best-practices-and-troubleshooting">Chapter 8: Regex Best Practices and Troubleshooting</h2>
<h3 id="heading-best-practices-to-consider-while-writing-regular-expressions">Best Practices to Consider While Writing Regular Expressions</h3>
<p>Over time, regular expressions can become complex and hard to understand, depending on the use case and purpose. Things may become more complicated if it takes you a long time to come back to them or you work in a team.</p>
<p>Luckily, there are a few best practices to consider while writing regular expressions so you can make things easier for yourself and your team members.</p>
<p>Here are those best practices:</p>
<ul>
<li><p><strong>Keep it simple and readable</strong>: a simple, easy-to-read, and effective regex is better than a complex and effective regex. If you can make the regex efficient without using the complex concept of non-capturing groups like lookarounds (lookaheads and lookbehinds), then don’t use them.</p>
</li>
<li><p><strong>Avoid greedy matches</strong>: metacharacters like <code>*</code> and <code>+</code> and the wildcard (<code>.</code>) are greedy by default. It's hard to do without them, but when you use them and they cause greediness, make sure you use the zero or one quantifier (<code>?</code>) on them. In addition, avoid using the wildcard where necessary.</p>
</li>
<li><p><strong>Use comments to describe what a regex does</strong>: if you're working in a team, try to explain what the regexes you write do so others can understand them without wasting time.</p>
</li>
<li><p><strong>Use online regex testers</strong>: instead of writing your regular expressions in your code editor, write them in regex testers where you can test what they match without writing some more code. Free online regex testers like regex101 and regexpal.com also play a role in debugging because they can highlight errors and tell you what's wrong. </p>
</li>
<li><p><strong>Escape special characters</strong>: if you want to perform a literal match on metacharacters like <code>.</code>, <code>*</code>, <code>+</code>, <code>{</code>, <code>}</code>, and others, don’t forget to escape them unless you're using them inside a character set. Sometimes, you even have to escape hyphens in a character set. </p>
</li>
</ul>
<h3 id="heading-how-to-write-accurate-regular-expressions">How to Write Accurate Regular Expressions</h3>
<p>Writing accurate regular expressions with precision requires understanding what you want to match, the pattern to use, attention to detail, and an understanding of the underlying syntax and behavior of regular expressions in general.</p>
<p>This is crucial in order to ensure there are no avoidable errors and make sure the regexes you write effectively match the desired string.</p>
<p>Here are some tips to help you write accurate regular expressions:</p>
<ul>
<li><p><strong>Understand the string you want to match</strong>: before you write the regex pattern to match a string, examine the string closely. Determine if you're targeting the whole string or a particular part of the string. If you're targeting a part of the string or you want to strip out some, look out for the pattern that you want follow. If you get familiar with the string, you can write a more accurate regex.</p>
</li>
<li><p><strong>Be specific</strong>: avoid using the wildcard where necessary. For instance, do not use the wildcard to match a number since you can use <code>\d</code> or <code>[0-9]</code>, or uppercase letters since you can use <code>[A-Z]</code>.</p>
</li>
<li><p><strong>Use quantifiers to shorten patterns</strong>: if you want a particular part of your regex to match repeated occurrences, try to use quantifiers like <code>+</code>, <code>*</code>, <code>{n,m}</code>, <code>{n,}</code>, and <code>{n}</code>. For instance, if you want to match a date with <code>/</code> as the separator, you can use the pattern <code>\d{1,2}\/\d{1,2}\/\d{4}</code> instead of <code>\d\d\/\d\d\/\d\d\d\d</code>.</p>
</li>
<li><p><strong>Use online regex testers</strong>: online regex testers like regexpal.com and regex101.com help you write more accurate regexes by giving you a live match preview, highlighting matches, and showing you errors their engines encounter while processing the regexes.</p>
</li>
<li><p><strong>Use word boundary to prevent unwanted matches</strong>: surrounding your pattern with the word boundary (<code>\b</code>) can help you prevent unnecessary and unwanted matches. For example, if you want to match a 6-digit zip code, <code>\d{6}</code> can do it for you but will also match any part of the string that has 6 digits that follow one another. What would do it better is <code>\b\d{6}\b</code>.</p>
</li>
</ul>
<p>Anchors (<code>^</code> and <code>$</code>) can also help prevent unwanted matches since they "anchor" a pattern to the start or end of the line. You can use them to make sure the match is found at the end or start of the line, or both. </p>
<p>For example:</p>
<ul>
<li><code>/^Hello/i</code> would only match <code>Hello</code> or <code>hello</code> at the start of a line</li>
<li><code>/Hello$/i</code> would only match <code>Hello</code> or <code>hello</code> at the end of a line</li>
<li><code>/^Hello$/i</code> would only match <code>Hello</code> or <code>hello</code> if it’s the only target string unless you have the multiline flag turned on and there's <code>Hello</code> or <code>hello</code> on another line.</li>
</ul>
<p>If you have issues getting things right with a regex pattern, online testing tools like regex101.com and regexpal.com can also help you step through the pattern bit by bit. There are also regex visualizers you can use to check what's wrong with your regex patterns. </p>
<p>One of those tools that I find amazing is Regulex (jex.im/regulex). It helps you put your regular expressions in a visual perspective you can export</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regulex-right.png" alt="regulex-right" width="600" height="400" loading="lazy"></p>
<p>And it can show you what goes wrong with your pattern:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regulex-wrong.png" alt="regulex-wrong" width="600" height="400" loading="lazy"></p>
<h2 id="heading-chapter-9-applications-of-regular-expressions">Chapter 9: Applications of Regular Expressions</h2>
<h3 id="heading-a-better-way-to-match-dates">A Better Way to Match Dates</h3>
<p>You've seen several patterns you can use to match dates in the <code>dd/mm/yyyy</code> format such as <code>\d\d\/\d\d\/\d\d\d\d</code>, <code>\d\d[/.-]\d\d[/.-]\d\d\d\d/;</code>, and <code>\d{1,2}\/\d{1,2}\/\d{4}</code>.</p>
<p>The problem is that those three patterns just check for the occurrence of a number, and not a valid date. For example, invalid dates <code>99/89/2022</code> or <code>42/32/1909</code> would still match those patterns:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/invalid-date-matches.png" alt="invalid-date-matches" width="600" height="400" loading="lazy"></p>
<p>The solution is that you must account for the acceptable day, month, and year:</p>
<ul>
<li>the day can be 1 or 2 digits</li>
<li>the day cannot exceed 31</li>
<li>the month cannot exceed 12</li>
<li>the year could be 2 or 4 digits, but never 1, 3, or greater than 4 digits</li>
</ul>
<p>You should also account for:</p>
<ul>
<li>a day that could start with 0, 1, 2, or 3, but never 4 or greater</li>
<li>a month that could start with 0, or 1, but never 2 or greater</li>
</ul>
<p>Here's the regex pattern that satisfies those conditions:</p>
<pre><code class="lang-console">/^(3[01]|[12][0-9]|0?[1-9])[-./](1[0-2]|0?[1-9])[-./](20[0-9]{2}|[0-9]{4}|[0-9]{2})$/gm
</code></pre>
<p>The image below is an illustration that labels each part of the pattern and explains what they do:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/regexdate--1-.png" alt="regexdate--1-" width="600" height="400" loading="lazy"></p>
<p>Here are the dates that match the pattern and those that do not:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/date-re-matches.png" alt="date-re-matches" width="600" height="400" loading="lazy"></p>
<p>You can take the pattern and test it against some dates in JavaScript:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re =
  <span class="hljs-regexp">/^(3[01]|[12][0-9]|0?[1-9])[-./](1[0-2]|0?[1-9])[-./](20[0-9]{2}|[0-9]{4}|[0-9]{2})$/</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">testDate</span>(<span class="hljs-params">date</span>) </span>{
  <span class="hljs-keyword">const</span> dateTester = re.test(date);
  <span class="hljs-built_in">console</span>.log(dateTester);
}

testDate(<span class="hljs-string">'12-01-2022'</span>); <span class="hljs-comment">// true</span>
testDate(<span class="hljs-string">'31.11.1999'</span>); <span class="hljs-comment">// true</span>
testDate(<span class="hljs-string">'02-01-21'</span>); <span class="hljs-comment">// true</span>
testDate(<span class="hljs-string">'42-01-2021'</span>); <span class="hljs-comment">// false</span>
testDate(<span class="hljs-string">'22-91-23'</span>); <span class="hljs-comment">// false</span>
</code></pre>
<p>You can see the date, month, year, and separator parts of the pattern are in their respective groups. If you want to match other formats like <code>mm/dd/yyyy</code> or <code>yyyy/mm/dd</code>, you can twist the pattern around.</p>
<p>You can even make the pattern a little shorter by putting the first separator in a group and referencing it for the second separator:</p>
<pre><code class="lang-console">^(3[01]|[12][0-9]|0?[1-9])([-./])(1[0-2]|0?[1-9])\2(20[0-9]{2}|[0-9]{4}|[0-9]{2})$
</code></pre>
<h3 id="heading-how-to-match-us-zip-codes">How to Match US Zip Codes</h3>
<p>The zip codes in the US are a 5-digit number, but they may also have a 4-digit extension, for example, <code>56893</code> or <code>56893-9232</code>.</p>
<p>The pattern <code>\b\d{5}\b</code> would match a 5-digit zip-code:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/zip-code-first-part-match.png" alt="zip-code-first-part-match" width="600" height="400" loading="lazy"></p>
<p>You also need to account for the other 4 digits and the hyphen between the two sets of numbers. The pattern, <code>\b\d{5}(\-\d{4})?\b</code> would do that for you.</p>
<p>Here's an image that labels each part of the pattern and explais what they do:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/zip-regex--1-.png" alt="zip-regex--1-" width="600" height="400" loading="lazy"></p>
<p>You can also take the regex and extract all the zip codes that are matches:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\b\d{5}(\-\d{4})?\b/g</span>;
<span class="hljs-keyword">const</span> zipCodes = [
  <span class="hljs-string">'56893'</span>,
  <span class="hljs-string">'ca58392bn'</span>,
  <span class="hljs-string">'29043'</span>,
  <span class="hljs-string">'90342-9014'</span>,
  <span class="hljs-string">'89435'</span>,
  <span class="hljs-string">'75034'</span>,
  <span class="hljs-string">'90453-3056'</span>,
  <span class="hljs-string">'12345-6789'</span>,
  <span class="hljs-string">'b458923'</span>,
  <span class="hljs-string">'589323'</span>,
];

<span class="hljs-keyword">const</span> matchedZipCodes = [];

<span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> zipCode <span class="hljs-keyword">of</span> zipCodes) {
  <span class="hljs-keyword">const</span> matches = zipCode.match(re);
  <span class="hljs-keyword">if</span> (matches) {
    matchedZipCodes.push(matches[<span class="hljs-number">0</span>]);
  }
}

<span class="hljs-built_in">console</span>.log(matchedZipCodes);

<span class="hljs-comment">/*
Output:
[
  '56893',
  '29043',
  '90342-9014',
  '89435',
  '75034',
  '90453-3056',
  '12345-6789'
]
*/</span>
</code></pre>
<p>And if you want the zip codes that are invalid, you can use the <code>filter()</code> array method to remove those that do not match the pattern:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> re = <span class="hljs-regexp">/\b\d{5}(\-\d{4})?\b/g</span>;
<span class="hljs-keyword">const</span> zipCodes = [
  <span class="hljs-string">'56893'</span>,
  <span class="hljs-string">'ca58392bn'</span>,
  <span class="hljs-string">'29043'</span>,
  <span class="hljs-string">'90342-9014'</span>,
  <span class="hljs-string">'89435'</span>,
  <span class="hljs-string">'75034'</span>,
  <span class="hljs-string">'90453-3056'</span>,
  <span class="hljs-string">'12345-6789'</span>,
  <span class="hljs-string">'b458923'</span>,
  <span class="hljs-string">'589323'</span>,
];

<span class="hljs-keyword">const</span> invalidZipCodes = zipCodes.filter(<span class="hljs-function">(<span class="hljs-params">zipCode</span>) =&gt;</span> !zipCode.match(re));

<span class="hljs-built_in">console</span>.log(invalidZipCodes); <span class="hljs-comment">// [ 'ca58392bn', 'b458923', '589323' ]</span>
</code></pre>
<h3 id="heading-how-to-match-email-addresses">How to Match Email Addresses</h3>
<p>Email addresses could be as simple as <code>john@email.com</code>, and as complex as you can ever imagine. So, there's no "one pattern" for validating email addresses. This also makes email validation a complex thing to do.</p>
<p>Validating emails with regex can also be a bit questionable because you can't stop anyone from making an email up. But still, there's a format you generally want the email address to be in whether it is made up or not. This is why you may want to use regular expressions to validate an email.</p>
<p>A pattern like <code>^/\w{4,}@\w{3,}\.\w{3,}$/</code> could be enough for validating simple and straightforward email addresses like <code>john@example.com</code>.</p>
<p>Here's an image that labels each part of the pattern and explains what they do:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/simpleEmailRegEx.png" alt="simpleEmailRegEx" width="600" height="400" loading="lazy"></p>
<p>And here are the emails that match:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/email-unreliable.png" alt="email-unreliable" width="600" height="400" loading="lazy"></p>
<p>As you can see, the pattern did not even match all the emails provided. That's because the pattern does not account for:</p>
<ul>
<li>emails with a period within usernames like <code>jane.doe@email.com</code> </li>
<li>second-level domain (SLD) extensions like <code>john@example.abc.com</code> </li>
<li>and country code second-level domains (ccSLDs) like <code>jane@email.co.uk</code></li>
</ul>
<p>In fact, a single email can even combine all the criteria listed above.</p>
<p>A better pattern for matching emails is <code>/^[\w.-]+@[a-zA-Z\d.-]+\.[a-zA-Z]{2,}$/</code>. </p>
<p>I also prepare an illustration that labels each part of the pattern and shows what they do:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/betterEmailRegEx.png" alt="betterEmailRegEx" width="600" height="400" loading="lazy"></p>
<p>This pattern matches an email address better than the first one:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/email-a-bit-reliable.png" alt="email-a-bit-reliable" width="600" height="400" loading="lazy"></p>
<p>According to the RFC 5322 specification, the pattern that works 99% of the time for validating email is this:</p>
<pre><code class="lang-console">(?:[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])
</code></pre>
<p><strong>N.B.</strong>: You should surround the pattern with anchors so it doesn’t leave out a part of a possible email and match the others. </p>
<p>This is what I'm trying to point out:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/matchingIvalidEmail.png" alt="matchingIvalidEmail" width="600" height="400" loading="lazy"></p>
<p>You can take that pattern into JavaScript and test it against some email addresses:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> emailRe =
  <span class="hljs-regexp">/^(?:[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&amp;'*+/=?^_`{|}~-]+)*|"(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9]))\.){3}(?:(2(5[0-5]|[0-4][0-9])|1[0-9][0-9]|[1-9]?[0-9])|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])$/</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">matchEmail</span>(<span class="hljs-params">email</span>) </span>{
  <span class="hljs-keyword">if</span> (emailRe.test(email)) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Valid email!'</span>);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Invalid email'</span>);
  }
}

matchEmail(<span class="hljs-string">'janedoe@email.com'</span>);
matchEmail(<span class="hljs-string">'john.doe@email.com'</span>);
matchEmail(<span class="hljs-string">'7@koala@email.com!'</span>);
matchEmail(<span class="hljs-string">'kayla.simpson@email.co.uk'</span>);
matchEmail(<span class="hljs-string">'kayla.simpson@email.co..uk'</span>);
</code></pre>
<p>As I pointed out earlier, matching email addresses with regex is a complex task. If you know the kind of email you'll be working with, it is better to tailor your regex for them. </p>
<p>Sometimes, to match an email, all you all you might need is a simple regex. Some other times, the pattern you need might be as complex as the one above.</p>
<h3 id="heading-how-to-match-passwords">How to Match Passwords</h3>
<p>To match passwords, you can use a lookahead – since lookaround groups generally don’t consume characters. But there are always multiple ways of doing the same thing in regular expressions, and programming in general of course.</p>
<p>You've seen a lookahead for matching 6-digit passwords already. This time around, let's say the password should not be less than 8 characters with at least one uppercase, one lowercase, one digit, and one symbol.</p>
<p>Here's the regex pattern that does just that:</p>
<pre><code class="lang-console">^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$?%"';^}{&amp;:*()∞+=-]).*$
</code></pre>
<p>Here are the passwords it matches:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/pword-matches.png" alt="pword-matches" width="600" height="400" loading="lazy"></p>
<p>You can take that into JavaScript and test it against possible passwords:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> passwordRe =
  <span class="hljs-regexp">/^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$?%"';^}{&amp;:*()∞+=-]).*$/gm</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">matchPassWord</span>(<span class="hljs-params">password</span>) </span>{
  <span class="hljs-keyword">if</span> (passwordRe.test(password)) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-literal">true</span>);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-literal">false</span>);
  }
}

matchPassWord(<span class="hljs-string">'johnDoe21^'</span>);
matchPassWord(<span class="hljs-string">'Strong@123'</span>);
matchPassWord(<span class="hljs-string">'weakpassword'</span>);
matchPassWord(<span class="hljs-string">'ABcd12$'</span>);
matchPassWord(<span class="hljs-string">'Longpassword1234!'</span>);
matchPassWord(<span class="hljs-string">'Short@1'</span>);
matchPassWord(<span class="hljs-string">'janEdoe34$'</span>);
</code></pre>
<p>You can also extract each of those group into its variable and test a password against it. This would let you show an error for that particular condition the password is trying to match:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> passwordLength = <span class="hljs-regexp">/(?=.{8,})/</span>,
  lowercaseChar = <span class="hljs-regexp">/(?=.*[a-z])/</span>,
  uppercaseChar = <span class="hljs-regexp">/(?=.*[A-Z])/</span>,
  numberChar = <span class="hljs-regexp">/(?=.*[0-9])/</span>,
  specialChar = <span class="hljs-regexp">/(?=.*[!@#$?%"';^}{&amp;:*()∞+=-])/</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">validatePassword</span>(<span class="hljs-params">password</span>) </span>{
  <span class="hljs-keyword">if</span> (
    passwordLength.test(password) &amp;&amp;
    lowercaseChar.test(password) &amp;&amp;
    uppercaseChar.test(password) &amp;&amp;
    numberChar.test(password) &amp;&amp;
    specialChar.test(password)
  ) {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Valid password!'</span>);
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Invalid Password'</span>);
  }
}

validatePassword(<span class="hljs-string">'johnDoe21^'</span>);
validatePassword(<span class="hljs-string">'Strong@123'</span>);
validatePassword(<span class="hljs-string">'weakpassword'</span>);
validatePassword(<span class="hljs-string">'ABcd12$'</span>);
validatePassword(<span class="hljs-string">'Longpassword1234!'</span>);
validatePassword(<span class="hljs-string">'Short@1'</span>);
validatePassword(<span class="hljs-string">'janEdoe34$'</span>);
</code></pre>
<h3 id="heading-form-validation-with-regex">Form Validation with Regex</h3>
<p>One of the most popular ways developers use regular expressions is form validation. Since a form usually has input fields like name, email, password, and others, you can write a regular expression for what you expect the user to put in those input fields.</p>
<p>I prepared a little website where I show you how to validate the name, username, email, and password fields of a form with regex. </p>
<p>Here's the HTML:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"styles.css"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"form-validate.js"</span> <span class="hljs-attr">defer</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Form Validation with RegEx<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"error-message"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">form</span> <span class="hljs-attr">action</span>=<span class="hljs-string">""</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Sign Up<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Fill in the form fields<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"name"</span>&gt;</span>Name<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"name"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"name"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"username"</span>&gt;</span>Username<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"text"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"username"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"username"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"email"</span>&gt;</span>Email<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"email"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"email"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"form-control"</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">label</span> <span class="hljs-attr">for</span>=<span class="hljs-string">"email"</span>&gt;</span>Password<span class="hljs-tag">&lt;/<span class="hljs-name">label</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"password"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"password"</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">input</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"submit"</span> <span class="hljs-attr">value</span>=<span class="hljs-string">"Submit"</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"submit"</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">form</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The CSS:</p>
<pre><code class="lang-css"><span class="hljs-keyword">@import</span> url(<span class="hljs-string">'https://fonts.googleapis.com/css2?family=Roboto&amp;display=swap'</span>);

* {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
  <span class="hljs-attribute">box-sizing</span>: border-box;
}

<span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#d0d0d5</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Roboto'</span>, sans-serif;
}

<span class="hljs-selector-tag">form</span> {
  <span class="hljs-attribute">position</span>: absolute;
  <span class="hljs-attribute">top</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">left</span>: <span class="hljs-number">50%</span>;
  <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">translate</span>(-<span class="hljs-number">50%</span>, -<span class="hljs-number">50%</span>);
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#3b3b4f</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.4rem</span> <span class="hljs-number">3rem</span> <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2px</span>;
}

<span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0.5rem</span> <span class="hljs-number">0</span>;
}

<span class="hljs-selector-id">#error-message</span> {
  <span class="hljs-attribute">background-color</span>: crimson;
  <span class="hljs-attribute">color</span>: <span class="hljs-number">#fff</span>;
  <span class="hljs-attribute">max-width</span>: <span class="hljs-number">80%</span>;
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">0.5rem</span> auto <span class="hljs-number">0</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.2rem</span> <span class="hljs-number">0.5rem</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">4px</span>;
}

<span class="hljs-selector-id">#error-message</span> <span class="hljs-selector-tag">p</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">14px</span>;
  <span class="hljs-attribute">text-align</span>: center;
}

<span class="hljs-selector-class">.form-control</span> {
  <span class="hljs-attribute">display</span>: flex;
  <span class="hljs-attribute">flex-direction</span>: column;
}

<span class="hljs-selector-class">.form-control</span> <span class="hljs-selector-tag">label</span> {
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">0.2rem</span>;
}

<span class="hljs-selector-class">.form-control</span> <span class="hljs-selector-tag">input</span> {
  <span class="hljs-attribute">width</span>: <span class="hljs-number">14rem</span>;
  <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">1.2rem</span>;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.2rem</span>;
  <span class="hljs-attribute">border</span>: <span class="hljs-number">2px</span> solid <span class="hljs-number">#d0d0d5</span>;
  <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">2px</span>;
}

<span class="hljs-selector-class">.form-control</span> <span class="hljs-selector-tag">input</span><span class="hljs-selector-pseudo">:focus</span> {
  <span class="hljs-attribute">outline</span>: none;
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">'submit'</span>]</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#fecc4c</span>;
  <span class="hljs-attribute">border-color</span>: <span class="hljs-number">#f1a02a</span>;
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">'Roboto'</span>, sans-serif;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.3rem</span>;
  <span class="hljs-attribute">border-width</span>: <span class="hljs-number">1px</span>;
  <span class="hljs-attribute">cursor</span>: pointer;
}

<span class="hljs-selector-tag">input</span><span class="hljs-selector-attr">[type=<span class="hljs-string">'submit'</span>]</span><span class="hljs-selector-pseudo">:hover</span> {
  <span class="hljs-attribute">background-color</span>: <span class="hljs-number">#e3bd53</span>;
}

<span class="hljs-selector-class">.hide</span> {
  <span class="hljs-attribute">display</span>: none;
}

<span class="hljs-selector-class">.show</span> {
  <span class="hljs-attribute">display</span>: block;
}

<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">768px</span>) {
  <span class="hljs-selector-id">#error-message</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0.5rem</span> auto <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.1rem</span> <span class="hljs-number">0.2rem</span>;
  }
}

<span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">max-width:</span> <span class="hljs-number">667px</span>) {
  <span class="hljs-selector-tag">form</span> {
    <span class="hljs-attribute">top</span>: <span class="hljs-number">61%</span>;
  }

  <span class="hljs-selector-id">#error-message</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0.2rem</span> auto <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.1rem</span> <span class="hljs-number">0.4rem</span>;
  }
}
</code></pre>
<p>Most importantly, some well-commented JavaScript that contains the patterns I used, and how I tested each of the patterns against the respective fields they correlate with:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Get the form element</span>
<span class="hljs-keyword">const</span> form = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'form'</span>);
<span class="hljs-comment">// Get the div element that shows the error(s)</span>
<span class="hljs-keyword">const</span> errorMessageDiv = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#error-message'</span>);

<span class="hljs-comment">// The RegEx patterns in a "patterns" object</span>
<span class="hljs-keyword">const</span> patterns = {
  <span class="hljs-attr">nameRe</span>: <span class="hljs-regexp">/^[a-zA-Z]{2,35}\s[a-zA-Z]{2,35}$/</span>, <span class="hljs-comment">// validates the name field</span>
  usernameRe: <span class="hljs-regexp">/^[a-zA-Z]{3,30}(\d{1,4})?$/</span>, <span class="hljs-comment">// validates the username field</span>
  emailRe: <span class="hljs-regexp">/^[\w.-]+@[a-zA-Z\d.-]+\.[a-zA-Z]{2,}$/</span>, <span class="hljs-comment">// validates the email field</span>
  passwordRe:
    <span class="hljs-regexp">/^(?=.{8,})(?=.*[a-z])(?=.*[A-Z])(?=.*[0-9])(?=.*[!@#$?%"';^}{&amp;:*()∞+=-]).*$/</span>, <span class="hljs-comment">// validates the password field</span>
};

<span class="hljs-comment">// Hide error message div when the page loads</span>
errorMessageDiv.style.display = <span class="hljs-string">'none'</span>;

<span class="hljs-comment">// Add a submit event to the form</span>
form.addEventListener(<span class="hljs-string">'submit'</span>, validateAndSubmitForm);

<span class="hljs-comment">// Form validation and submit function</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">validateAndSubmitForm</span>(<span class="hljs-params">e</span>) </span>{
  e.preventDefault();

  <span class="hljs-comment">// Clear previous error messages</span>
  errorMessageDiv.innerHTML = <span class="hljs-string">''</span>;

  <span class="hljs-keyword">let</span> nameInputValue = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#name'</span>).value;
  <span class="hljs-keyword">let</span> usernameInputValue = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#username'</span>).value;
  <span class="hljs-keyword">let</span> emailInputValue = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#email'</span>).value;
  <span class="hljs-keyword">let</span> passwordInputValue = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#password'</span>).value;

  <span class="hljs-comment">// Validate Name</span>
  <span class="hljs-keyword">if</span> (!patterns.nameRe.test(nameInputValue)) {
    showError(<span class="hljs-string">'Name must have first name and last name separated by a space'</span>);
  }

  <span class="hljs-comment">// Validate Username</span>
  <span class="hljs-keyword">if</span> (!patterns.usernameRe.test(usernameInputValue)) {
    showError(
      <span class="hljs-string">'Username must have between 3 and 30 characters and can include up to 4 digits at the end'</span>
    );
  }

  <span class="hljs-comment">// Validate Email</span>
  <span class="hljs-keyword">if</span> (!patterns.emailRe.test(emailInputValue)) {
    showError(<span class="hljs-string">'Enter a valid email address'</span>);
  }

  <span class="hljs-comment">// Validate Password</span>
  <span class="hljs-keyword">if</span> (!patterns.passwordRe.test(passwordInputValue)) {
    showError(
      <span class="hljs-string">'Password must contain at least 8 characters, one lowercase letter, one uppercase letter, one digit, and one special character.'</span>
    );
  }

  <span class="hljs-comment">// If there are no error messages, the form is valid, so you can submit it</span>
  <span class="hljs-keyword">if</span> (errorMessageDiv.innerHTML === <span class="hljs-string">''</span>) {
    <span class="hljs-built_in">console</span>.log(nameInputValue);
    <span class="hljs-built_in">console</span>.log(usernameInputValue);
    <span class="hljs-built_in">console</span>.log(emailInputValue);
    <span class="hljs-built_in">console</span>.log(passwordInputValue);

    <span class="hljs-comment">// Hide the errorMessageDiv element since there are no errors</span>
    errorMessageDiv.style.display = <span class="hljs-string">'none'</span>;

    <span class="hljs-comment">// Greet user</span>
    alert(<span class="hljs-string">`Hi <span class="hljs-subst">${usernameInputValue}</span> 👋🏽 \nThanks for filling this form`</span>);

    <span class="hljs-comment">// Clear input fields with the reset() method</span>
    <span class="hljs-built_in">document</span>.forms[<span class="hljs-number">0</span>].reset();
  } <span class="hljs-keyword">else</span> {
    <span class="hljs-comment">// Show the errorMessageDiv element if there are errors</span>
    errorMessageDiv.style.display = <span class="hljs-string">'block'</span>;
  }
}

<span class="hljs-comment">// The function responsible for showing error(s)</span>
<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">showError</span>(<span class="hljs-params">message</span>) </span>{
  <span class="hljs-keyword">const</span> errorMessageElement = <span class="hljs-built_in">document</span>.createElement(<span class="hljs-string">'p'</span>);

  errorMessageElement.innerText = message;
  errorMessageDiv.appendChild(errorMessageElement);
}
</code></pre>
<p>This is what the form does:
<img src="https://www.freecodecamp.org/news/content/images/2023/07/form-validation.gif" alt="form-validation" width="600" height="400" loading="lazy"></p>
<p>You can grab all the code in this <a target="_blank" href="https://github.com/Ksound22/regex-bk-form-validator">GitHub repo</a>.</p>
<h3 id="heading-article-table-of-contents-generator">Article Table of Contents Generator</h3>
<p>You can leverage the power of regular expressions to create a markdown table of contents generator.</p>
<p>Markdown tables of contents are made up of <code>h2</code> headings at the top level. Those <code>h2</code> headings have an <code>id</code> attribute you can use as the link. If you take a look at those <code>id</code> attributes, they are in the format below:</p>
<pre><code class="lang-console">[How to Do ABC on XYZ!!!](##howtodoabconxyz)
</code></pre>
<p>This means you need to:</p>
<ul>
<li>use the text as it is as the link text and surround them with curly braces</li>
<li>replace all spaces with an empty string</li>
<li>replace all symbols with an empty string</li>
<li>convert all the letters to lowercase</li>
<li>surround the new link with parenthesis</li>
</ul>
<p>The <code>replace()</code> and <code>lowerCase()</code> string methods will help you achieve those things.</p>
<p>Here's the HTML for the app:</p>
<pre><code class="lang-js">&lt;!DOCTYPE html&gt;
&lt;html lang="en"&gt;

&lt;head&gt;
    &lt;meta charset="UTF-8"&gt;
    &lt;meta name="viewport" content="width=device-width, initial-scale=1.0"&gt;
    &lt;link rel="stylesheet" href="styles.css"&gt;
    &lt;script src="toc.js" defer&gt;&lt;/script&gt;
    &lt;title&gt;TOC Generator&lt;/title&gt;
&lt;/head&gt;

&lt;body&gt;
    &lt;div class="alert" id="alert"&gt;
        Please enter some heading texts!
    &lt;/div&gt;

    &lt;h1&gt;Markdown Table of Content Generator for your Next Article&lt;/h1&gt;
    &lt;h2&gt;Paste in your headings to generate table of content&lt;/h2&gt;
    &lt;form action=""&gt;

        &lt;div class="form"&gt;
            &lt;div class="form-control"&gt;
                &lt;textarea name="toc" id="toc" cols="40" rows="15"&gt;&lt;/textarea&gt;
            &lt;/div&gt;

            &lt;div class="form-control"&gt;
                &lt;input type="submit" value="Generate" id="submit"&gt;
            &lt;/div&gt;
        &lt;/div&gt;
    &lt;/form&gt;

    &lt;div id="generated-toc"&gt;
        &lt;!-- &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt;
        &lt;p&gt;Lorem ipsum dolor sit amet consectetur.&lt;/p&gt; --&gt;
    &lt;/div&gt;

&lt;/body&gt;

&lt;/html&gt;
</code></pre>
<p>The CSS:</p>
<pre><code class="lang-js">@<span class="hljs-keyword">import</span> url(<span class="hljs-string">'https://fonts.googleapis.com/css2?family=Poppins&amp;family=Roboto&amp;display=swap'</span>);

* {
  <span class="hljs-attr">margin</span>: <span class="hljs-number">0</span>;
  padding: <span class="hljs-number">0</span>;
  box-sizing: border-box;
}

body {
  font-family: <span class="hljs-string">'Poppins'</span> sans-serif;
  background-color: #<span class="hljs-number">3</span>b3b4f;
  color: #fff;
}

h1 {
  margin-top: <span class="hljs-number">2</span>rem;
}

h1,
h2 {
  text-align: center;
  color: black;
  margin-bottom: <span class="hljs-number">1</span>rem;
  color: white;
}

form {
  max-width: <span class="hljs-number">90</span>%;
  margin: <span class="hljs-number">0</span> auto;
  background-color: #d0d0d5;
  padding: <span class="hljs-number">2</span>rem;
  border-radius: <span class="hljs-number">2</span>px;
}

.form-control {
  text-align: center;
}

textarea {
  <span class="hljs-attr">padding</span>: <span class="hljs-number">0.2</span>rem <span class="hljs-number">2</span>rem <span class="hljs-number">1</span>rem <span class="hljs-number">0.2</span>rem;
}

<span class="hljs-attr">textarea</span>:focus {
  <span class="hljs-attr">outline</span>: <span class="hljs-number">1</span>px solid #<span class="hljs-number">3</span>b3b4f;
}

input[type=<span class="hljs-string">'submit'</span>] {
  font-family: <span class="hljs-string">'Poppins'</span>, sans-serif;
  font-size: <span class="hljs-number">1.1</span>rem;
  border: none;
  background-color: #<span class="hljs-number">03732</span>e;
  color: #fff;
  padding: <span class="hljs-number">0.5</span>rem <span class="hljs-number">1</span>rem;
  border-radius: <span class="hljs-number">4</span>px;
  margin-top: <span class="hljs-number">1</span>rem;
  transition: <span class="hljs-number">0.3</span>s;
}

input[type=<span class="hljs-string">'submit'</span>]:hover {
  <span class="hljs-attr">cursor</span>: pointer;
  background-color: #<span class="hljs-number">00471</span>b;
}

#generated-toc {
  max-width: <span class="hljs-number">60</span>%;
  margin: <span class="hljs-number">1</span>rem auto;
  background-color: #d0d0d5;
  color: black;
  padding: <span class="hljs-number">2</span>rem;
  border-radius: <span class="hljs-number">2</span>px;
  text-align: left;
  font-size: <span class="hljs-number">1.1</span>rem;
  display: none;
}

.alert {
  <span class="hljs-attr">display</span>: none;
  margin: <span class="hljs-number">1</span>rem auto;
  max-width: <span class="hljs-number">20</span>%;
  text-align: center;
  padding: <span class="hljs-number">1</span>rem <span class="hljs-number">0</span>;
  border-radius: <span class="hljs-number">2</span>px;
  background-color: #eb7189;
  color: black;
}

@media screen and (max-width: <span class="hljs-number">768</span>px) {
  textarea {
    <span class="hljs-attr">width</span>: <span class="hljs-number">16</span>rem;
  }

  .alert {
    max-width: <span class="hljs-number">50</span>%;
  }
}
</code></pre>
<p>And the well-commented JavaScript:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> form = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'form'</span>);
<span class="hljs-keyword">const</span> generatedToc = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#generated-toc'</span>);
<span class="hljs-keyword">const</span> alert = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'.alert'</span>);

<span class="hljs-comment">// Regular expressions to remove spaces and special characters</span>
<span class="hljs-keyword">const</span> spaceRe = <span class="hljs-regexp">/\s+/g</span>;
<span class="hljs-keyword">const</span> symRe = <span class="hljs-regexp">/[°?+*$∞^%$#@!.,©:&amp;;"=%'_\[\]–\/\\&lt;&gt;|÷™®)£(}{€¥¢—“”‘•~]/g</span>;

<span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">generateToc</span>(<span class="hljs-params">e</span>) </span>{
  e.preventDefault();

  <span class="hljs-comment">// Get the heading texts from the textarea</span>
  <span class="hljs-keyword">const</span> headingTexts = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#toc'</span>).value;

  <span class="hljs-keyword">if</span> (headingTexts === <span class="hljs-string">''</span>) {
    <span class="hljs-comment">// Alert the user to enter heading texts</span>
    alert.style.display = <span class="hljs-string">'block'</span>;

    <span class="hljs-comment">// hide the alert after 3 seconds</span>
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      alert.style.display = <span class="hljs-string">'none'</span>;
    }, <span class="hljs-number">3000</span>);

    <span class="hljs-comment">// hide generated table of content (if any) since the user is trying to paste in another one</span>
    generatedToc.style.display = <span class="hljs-string">'none'</span>;
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-comment">// Split the heading texts into an array of lines</span>
  <span class="hljs-keyword">const</span> headingLines = headingTexts.split(<span class="hljs-string">'\n'</span>);

  <span class="hljs-comment">// Create an initial empty variable to save the table of content inside later</span>
  <span class="hljs-keyword">let</span> tocContent = <span class="hljs-string">''</span>;

  <span class="hljs-comment">// Loop through each line and generate the table of content items</span>
  headingLines.forEach(<span class="hljs-function">(<span class="hljs-params">headingLine</span>) =&gt;</span> {
    <span class="hljs-comment">// Remove any leading and/or trailing spaces from the line</span>
    headingLine = headingLine.trim();

    <span class="hljs-comment">// skip empty lines</span>
    <span class="hljs-keyword">if</span> (headingLine === <span class="hljs-string">''</span>) {
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">// Generate the TOC link based on the heading text(s)</span>
    <span class="hljs-keyword">const</span> markdownLink = headingLine
      .replace(spaceRe, <span class="hljs-string">''</span>) <span class="hljs-comment">// replace spaces with an empty string</span>
      .replace(symRe, <span class="hljs-string">''</span>) <span class="hljs-comment">// replace special characters (symbols)</span>
      .toLowerCase(); <span class="hljs-comment">// convert the link texts to lowercase characters</span>

    <span class="hljs-comment">// Create the table of contents item and append it to the tocContent variable</span>
    tocContent += <span class="hljs-string">`&lt;p&gt;• [<span class="hljs-subst">${headingLine}</span>](#<span class="hljs-subst">${markdownLink}</span>)&lt;/p&gt;`</span>;
  });

  <span class="hljs-comment">// Insert the generated table of contents into the "generated-toc" div element</span>
  generatedToc.innerHTML = tocContent;

  <span class="hljs-comment">// hide alert since there's currently no error at this point</span>
  alert.style.display = <span class="hljs-string">'none'</span>;

  <span class="hljs-comment">// show the "generated-toc" div</span>
  generatedToc.style.display = <span class="hljs-string">'block'</span>;

  <span class="hljs-comment">// clear the heading texts in the text area</span>
  <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">'#toc'</span>).value = <span class="hljs-string">''</span>;
}

<span class="hljs-comment">// Add a submit event to the form</span>
form.addEventListener(<span class="hljs-string">'submit'</span>, generateToc);

<span class="hljs-comment">/*
What is HTML?
How to Contribute$ To Open Source Like a Boss!!
Why you should Learn to C$ode in Java?

Why you should get into Web3!
Don't Attach Question Mark(?) to Hows!
Stop Scaring Newbies!
Why are you too cold&amp;
*/</span>
</code></pre>
<p>Here's what's happening in the app:</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/07/tocgen.gif" alt="tocgen" width="600" height="400" loading="lazy"></p>
<p>You can look through the code to have more understanding of how I was able to do that. The code is available on this <a target="_blank" href="https://github.com/Ksound22/regex-bk-form-validator">GitHub repo</a> and the app is <a target="_blank" href="https://astonishing-dolphin-948101.netlify.app/">live here</a>.</p>
<h2 id="heading-glossary-and-references">Glossary and References</h2>
<h3 id="heading-glossary-of-terms">Glossary of Terms</h3>
<ul>
<li><code>Regular Expression</code> or <code>RegEx</code>: A you can use for matching, searching, and manipulating text.</li>
<li><code>Pattern</code> or <code>regex pattern</code>: A sequence of characters that defines a search criterion in a regular expression.</li>
<li><code>Literal Character</code>: A character that matches itself in a regular expression (for example, "a" matches the character "a").</li>
<li><code>Flag</code>: Modifiers added after the closing delimiter of a regex to change matching behavior, such as <code>i</code> (case-insensitive) or <code>g</code> (global).</li>
<li><code>Metacharacter</code>: A character with a special meaning in a regular expression. Examples include <code>.</code> (any character), <code>*</code> (zero or more), and <code>|</code> (alternation).</li>
<li><code>Quantifier</code>: A metacharacter that specifies the number of repetitions of the preceding element. For example, <code>*</code> matches zero or more occurrences, and <code>{n}</code> matches <code>n</code> character(s).</li>
<li><code>Anchors</code>: Metacharacters that represent positions in the input string, such as <code>^</code> (start of line) and <code>$</code> (end of line).</li>
<li><code>Grouping</code>: Using parentheses <code>()</code> to create a subexpression you can repeat or reference as a single unit.</li>
<li><code>Capture Group</code>: A group in a regular expression that captures and stores the matched text for later use.</li>
<li><code>Non-Capturing Group</code>: A group in a regular expression that matches the pattern but does not capture the matched text.</li>
<li><code>Greedy</code>: A matching behavior where quantifiers try to match as much as possible.</li>
<li><code>Lazy</code>: Another matching behavior where quantifiers match as little as possible. It is the opposite of <code>greedy</code>.</li>
<li><code>Lookahead</code>: A zero-width assertion that looks ahead to see if a pattern exists without including it in the match.</li>
<li><code>Lookbehind</code>: A zero-width assertion that looks behind to see if a pattern exists without including it in the match.</li>
<li><code>Escape Sequence and Character</code>: Using a backslash <code>\</code>to escape a metacharacter to treat it as a literal character. Or using it before a character to match its special meaning instead of the literal character. For example, <code>\d</code>.</li>
<li><code>Word Boundary</code>: A zero-width assertion that matches the position between a word character and a non-word character.</li>
<li><code>Negated Character Class</code>: A character class with <code>^</code> as the first character, matching any character not in the class.</li>
<li><code>Regex Engine</code>: The underlying software component that processes regular expressions and performs matching.</li>
<li><code>Case Sensitive</code>: A matching behavior where letters' cases must exactly match in the regex pattern and the input string.</li>
<li><code>Case Insensitive</code>: A flag (<code>i</code>) that enables case-insensitive matching in the regular expression.</li>
<li><code>Shorthand Character Class</code>: Shortcuts for common character classes, such as <code>\d</code> (digit), <code>\w</code> (word character), and <code>\s</code> (whitespace).</li>
<li>Backreference: Referring to a captured group's content in the regex pattern. For example, <code>\1</code>.</li>
<li>Alternation: Using the <code>|</code> metacharacter to match either of two patterns.</li>
<li>JavaScript RegExp Object: The built-in JavaScript object that represents a regular expression. It has methods like <code>test()</code> and <code>exec()</code> for working with regular expressions.</li>
<li><code>Regular Expression Literals</code>: Regular expressions defined using slashes <code>/.../</code>, e.g., <code>/regex-pattern/</code>.</li>
<li>RegExp Constructor: The RegExp constructor for creating regular expressions dynamically.</li>
</ul>
<h3 id="heading-quick-reference-of-metacharacters-and-quantifiers">Quick Reference of Metacharacters and Quantifiers</h3>
<ul>
<li><code>\d</code>: matches any digit (0-9).</li>
<li><code>\D</code>: matches any non-digit character.</li>
<li><code>\w</code>: matches any word character (alphanumeric characters and underscore).</li>
<li><code>\W</code>: matches any non-word character.</li>
<li><code>\s</code>: matches any whitespace character (space, tab, newline, carriage return).</li>
<li><code>\S</code>: matches any non-whitespace character.</li>
<li><code>\b</code>: matches a word boundary position.</li>
<li><code>\B</code>: matches a non-word boundary position.</li>
<li><code>^</code>: matches the start of the line.</li>
<li><code>$</code>: matches the end of the line.</li>
<li><code>.</code>: matches any character except newline.</li>
<li><code>*</code>: matches zero or more occurrences.</li>
<li><code>+</code>: matches one or more occurrences.</li>
<li><code>?</code>: matches zero or one occurrence.</li>
<li><code>{n}</code>: matches exactly <code>n</code> (number) occurrences.</li>
<li><code>{n,}</code>: matches <code>n</code> or more occurrences.</li>
<li><code>{n,m}</code> matches at least <code>n</code> and at most <code>m</code> (another number) occurrences.</li>
<li><code>|</code>: matches either the left or right expression.</li>
<li><code>(...)</code>: capturing group.</li>
<li><code>(?:...)</code>: non-capturing group.</li>
<li><code>\</code>: escapes a metacharacter in order to match it literally, or escapes a metacharacter that is also a literal character. For example, <code>\d</code>.</li>
<li><code>[...]</code>: character class.</li>
<li><code>[^...]</code>: negated character class.</li>
<li><code>(?=...)</code>:  positive lookahead.</li>
<li><code>(?!...)</code>: negative lookahead.</li>
<li><code>(?&lt;=...)</code> positive lookbehind.</li>
<li><code>(?&lt;!...)</code>: negative lookbehind.</li>
</ul>
<p>Thank you for reading!</p>
 ]]>
                </content:encoded>
            </item>
        
            <item>
                <title>
                    <![CDATA[ Astro UI Framework [Full Book] ]]>
                </title>
                <description>
                    <![CDATA[ By Emmanuel Ohans Astro is a new UI framework that's designed for speed. And if you want to learn how to use it, you've come to the right place.  Table of Contents Introduction  Chapter 1: Build your first Astro Application  Chapter 2: Astro Compone... ]]>
                </description>
                <link>https://www.freecodecamp.org/news/how-to-use-the-astro-ui-framework/</link>
                <guid isPermaLink="false">66d45e54bc9760a197a1039c</guid>
                
                    <category>
                        <![CDATA[ book ]]>
                    </category>
                
                    <category>
                        <![CDATA[ TypeScript ]]>
                    </category>
                
                    <category>
                        <![CDATA[ User Interface ]]>
                    </category>
                
                    <category>
                        <![CDATA[ Web Development ]]>
                    </category>
                
                <dc:creator>
                    <![CDATA[ freeCodeCamp ]]>
                </dc:creator>
                <pubDate>Wed, 12 Jul 2023 20:58:29 +0000</pubDate>
                <media:content url="https://www.freecodecamp.org/news/content/images/2023/06/large-heading.png" medium="image" />
                <content:encoded>
                    <![CDATA[ <p>By Emmanuel Ohans</p>
<p>Astro is a new UI framework that's designed for speed. And if you want to learn how to use it, you've come to the right place. </p>
<h2 id="heading-table-of-contents">Table of Contents</h2>
<ol>
<li><a class="post-section-overview" href="#heading-introduction">Introduction</a> </li>
<li><a class="post-section-overview" href="#heading-chapter-1-build-your-first-astro-application">Chapter 1: Build your first Astro Application</a> </li>
<li><a class="post-section-overview" href="#heading-chapter-2-astro-components-in-depth">Chapter 2: Astro Components In-depth</a> </li>
<li><a class="post-section-overview" href="#heading-chapter-3-build-your-own-component-island">Chapter 3: Build Your Own Component Island</a> </li>
<li><a class="post-section-overview" href="#heading-chapter-4-the-secret-life-of-astro-component-islands">Chapter 4: The Secret Life of Astro Component Islands</a> </li>
<li><a class="post-section-overview" href="#heading-chapter-5-oh-my-react-how-to-build-a-react-documentation-site-clone">Chapter 5: Oh my React! (How to Build a React Documentation Site Clone)</a> </li>
<li><a class="post-section-overview" href="#heading-chapter-6-server-side-rendering-ssr-in-astro">Chapter 6: Server-side Rendering (SSR) in Astro</a> </li>
<li><a class="post-section-overview" href="#heading-chapter-7-be-audible-how-to-build-a-fullstack-astro-project">Chapter 7: Be Audible! (How to Build a Fullstack Astro Project)</a></li>
<li><a class="post-section-overview" href="#heading-chapter-8-build-your-own-astro-integrations">Chapter 8: Build Your Own Astro Integrations</a> </li>
<li><a class="post-section-overview" href="#conclusion-6">Conclusion</a> </li>
</ol>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-132.png" alt="Image" width="600" height="400" loading="lazy"></p>
<h1 id="heading-introduction">Introduction</h1>
<p>I'm not one of those bandwagon-jumping folks who drool over every shiny new library or framework that hits the scene just because it's trending. I'm more of a "wait-and-see" kinda person.</p>
<p>So, you're probably wondering why I wrote a book about the reasonably new UI framework, Astro.</p>
<p>Well, let me tell you.</p>
<p>I’ve been in this game for almost a decade now, and I've seen frameworks come and go like a bad case of indigestion. And Astro may not live forever, either.</p>
<p>But here's the thing: when you use a new UI framework, it's not just about getting stuff to work and slapping some apps together willy-nilly. No, no, no. The real magic lies in understanding the principles and concepts behind the framework's creation. And that's exactly the mindset I had when I wrote this book.</p>
<p>You’ve got to ask yourself: what makes this framework so unique? How is it different from all the other fluff out there? How can you apply its mental model to the bigger picture of developing applications for the web? Plus, what framework-agnostic principles can you pick up along the way?</p>
<p>The good news is I've got answers to all these burning questions sprinkled throughout the book like confetti.</p>
<p>Now, let's talk about performance, shall we? Of course, that’s a whole different ballgame depending on what kind of application you're dealing with. But for specific applications, for example content-focused applications, Astro is a total game-changer. Its performance defaults are off the charts.</p>
<p>The more I researched Astro, the more I was fascinated to write this book.</p>
<p>And here's the kicker: this book goes beyond just Astro. In specific chapters, we will discuss concepts you can apply to whatever framework you work with. And that's not just cool – that’s downright practical.</p>
<p>Astro is paving the way for a new architecture on the web: the component island architecture. And my goal is to help you understand it well enough to build some seriously robust production applications.</p>
<p>So, don't just scratch the surface. Instead, let’s dive deep and get to know this framework.</p>
<p>This is why I am writing this book. And hey, six months in, and I’m still loving it.</p>
<p>So, what are you waiting for? Grab your favourite drink (tea over coffee, here), dig in, and let's get building!</p>
<p>Cheers 🥂</p>
<h2 id="heading-a-note-about-this-book">A Note About This Book</h2>
<p>Okay, if you haven’t already noticed, I write like I speak. I use plain language and analogies that even my nan could (potentially) understand — when I do it right.</p>
<p>This book does not read in a typical technical documentation style—sorry, fellow nerds.</p>
<p>In my opinion, technical books should be easy on the eyes and a breeze to read. And why not have a bit of a laugh while we're at it?</p>
<p>If you're up for a good time while you learn a thing or two (well, a lot more), then let's get cracking!</p>
<h2 id="heading-this-book-vs-the-official-documentation">This Book vs the Official Documentation</h2>
<p>Some resources just parrot the official documentation. But I don't find these very helpful.</p>
<p>As such, this book differs from the official documentation in a couple of ways:</p>
<ul>
<li><strong>The tone of writing</strong>: this book adopts a non-technical documentation writing style for ease of understanding. Whether you appreciate this or not is left to your taste.</li>
<li><strong>Doesn’t follow the Diataxis framework</strong>: the Astro technical documentation is written following the <a target="_blank" href="https://diataxis.fr/">Diataxis</a> framework. The framework suggests structuring content around four distinct types: tutorial, how-to-guide, explanation, and reference.<br>This book breaks out of this strict structure to emphasise understanding and practical learning. This book is not a reference and doesn’t aim to replace the official Astro references. In the Diataxis lingo, understanding Astro may be defined as a mix of how-to guides and a careful blend of tutorials with elaborate explanations interwoven.</li>
<li><strong>Advanced usage</strong>: some advanced Astro uses are tucked away in the official references – without explanations or practical examples. This is perfectly fine for a documentation site. Experienced engineers can spend time digging into these. However, this book bridges the gap.<br>For example, consider building custom Astro integrations. You will not find a better (practical) resource than this book.</li>
<li><strong>Real-world applications</strong>: sometimes, to piece together a puzzle, it’s essential to see it at play in near real-world examples. This book explains important concepts and goes beyond that to put them to practice in comparative real-world examples.</li>
<li><strong>Saves time</strong>: This book will save you countless hours tinkering with references and code samples as a by-product of the above distinctions. Yes, you can spend hours digging deep into the docs or Astro source code, but I’ve spent hours (months, actually) doing so! So I can present the learnings without you doing as much of the work. But don’t be fooled – you still have to do the work of reading the book.</li>
</ul>
<p>Consider reading (or skimming) the official documentation after reading this book or using it as a reference. This book complements the official docs, it does not replace them.</p>
<h2 id="heading-how-the-book-is-structured">How the Book is Structured</h2>
<p>Every chapter in this book is one of the following:</p>
<ol>
<li>A concept chapter</li>
<li>A project chapter</li>
<li>A project and concept chapter</li>
</ol>
<p>The mix of these different chapter types will keep you engaged and make your learning effective. Remember, the goal is proper understanding.</p>
<h3 id="heading-concept-chapters">Concept chapters</h3>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/05/concept@2x.png" alt="Concept chapters are the foundational chapters for the rest of the book." width="1190" height="578" loading="lazy">
<em>Concept chapters are the foundational chapters for the rest of the book.</em></p>
<p>In concept chapters, we’ll learn the core concepts of Astro. These chapters will include code examples and throwaway applications. We will build no real-world projects in these chapters.</p>
<h3 id="heading-project-chapters">Project chapters</h3>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/05/build.png" alt="Showtime! Bring together what we've learned to build a real-world project. " width="1190" height="578" loading="lazy">
<em>Showtime! Bring together what we've learned to build a real-world project.</em></p>
<p>In project chapters, we’ll apply previous concepts we’ve learned towards building a near real-world project.</p>
<h3 id="heading-concept-and-project-chapters">Concept and project chapters</h3>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/05/concept-and-build.png" alt="Bring together the best of the worlds. Build and learn new concepts along the way." width="1190" height="578" loading="lazy">
<em>Bring together the best of the worlds. Build and learn new concepts along the way.</em></p>
<p>A project and concept chapter focuses on building a real-world application while introducing new concepts.</p>
<h2 id="heading-chapters-overview">Chapters Overview</h2>
<p>Below’s a summary of the chapters of the book:</p>
<h3 id="heading-chapter-1-build-your-first-application-with-astro">Chapter 1: Build your first application with Astro</h3>
<p>The book begins hands-on with a project and concept chapter.</p>
<p>In this chapter, we’ll learn the basics of Astro while building a feature-rich personal website.</p>
<h3 id="heading-chapter-2-astro-components-in-depth">Chapter 2: Astro components in-depth</h3>
<p>This is a concept chapter that goes in-depth into Astro components. We will go beyond the basics and master (arguably) the essential Astro entity.</p>
<p>We will start by exploring an argument to ditch the JavaScript runtime overhead where appropriate. We will then study the behaviour of Astro component markup, styles and scripts, and the powerful template syntax.</p>
<h3 id="heading-chapter-3-build-your-own-component-island">Chapter 3: Build your own component island</h3>
<p>This project chapter moves away from Astro and considers the component island architecture in isolation.</p>
<p>We will consider an overview of application rendering, comprehend the island architecture from the ground up, and build our own implementation from scratch.</p>
<p>This chapter will solidify your fundamental knowledge of the new web performance-focused architecture pattern.</p>
<h3 id="heading-chapter-4-the-secret-life-of-astro-component-islands">Chapter 4: The Secret Life of Astro Component Islands</h3>
<p>This is a concept chapter where we’ll get hands-on experience working with framework components in Astro. I’ll introduce you to responsible hydration and why it matters.</p>
<p>We will build many throwaway applications to explore how component islands work in Astro and why they are significant.</p>
<h3 id="heading-chapter-5-oh-my-react-the-react-documentation-site-clone">Chapter 5: Oh My React! (The React Documentation Site Clone)</h3>
<p>In this project and concept chapter, we will explore techniques for handling large amounts of content within an Astro application. Additionally, we will examine real-world use cases to provide practical examples.</p>
<p>This chapter will solidify the previous concepts learned and introduce some new ones while we build out a clone of the React documentation site with production best practices.</p>
<h3 id="heading-chapter-6-server-side-rendering-ssr-in-astro">Chapter 6: Server-side rendering (SSR) in Astro</h3>
<p>This concept chapter will explore server-side rendering and the new features unlocked in an Astro server-side rendered application. We will explore dynamic routing, API endpoints, Server streaming, and much more.</p>
<h3 id="heading-chapter-7-be-audible-full-stack-astro-project">Chapter 7: Be Audible! (Full stack Astro Project)</h3>
<p>This project chapter will take you beyond static sites into building full stack applications with Astro. In this chapter, I’ll argue that if you can build the app as an MPA and leverage component islands, you can build it with Astro.</p>
<h3 id="heading-chapter-8-build-your-own-astro-integrations">Chapter 8: Build your own Astro integrations</h3>
<p>This is a project and concept chapter where we’ll answer the question, what happens when you want a feature outside what Astro provides by default?</p>
<p>We will leverage hooks into Astro’s build process to build custom functionalities. These are called Astro integrations.</p>
<h3 id="heading-chapter-9-conclusion">Chapter 9: Conclusion</h3>
<p>Here, we will step back and appreciate how far we’ve come. Then we will reiterate the features that make Astro stand out. Features you’ve already seen in practice!</p>
<p>This is where our journey likely ends, and your journey into the world of Astro begins.</p>
<h2 id="heading-prerequisites">Prerequisites</h2>
<p>I tried to make this book “work for everyone”, but that’s incredibly difficult.</p>
<p>So, to make the best out of this book:</p>
<ul>
<li>You should already know some HTML, CSS and JS: this is not a web development beginner guide.</li>
<li>You should already know the basics of TypeScript: I don’t expect you to be a TypeScript champion, but surface-level understanding will prepare you for all the TypeScript in this book.</li>
</ul>
<p>I wrote this book specifically for mid, senior, and senior+ engineers, and the book contains chapters of varying technical difficulty. But I’ve done my best to explain these clearly and visually to satisfy different skill levels.</p>
<h2 id="heading-typographic-conventions">Typographic Conventions</h2>
<p>When text is written in a monospaced font, it typically represents code samples. These samples may be self-contained fragments or refer to a specific section of an application's code.</p>
<p>Below’s an example:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> { author } = Astro.props;
<span class="hljs-keyword">const</span> book = <span class="hljs-string">"Understanding Astro.js"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">data-name</span>=<span class="hljs-string">{book}</span>&gt;</span>A new book<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p>Sometimes, to show the source of the code, I added a comment to the file path at the top of the code block, as shown below:</p>
<pre><code class="lang-js">{<span class="hljs-comment">/** 📂 src/pages/index.astro **/</span>}
---
<span class="hljs-keyword">const</span> { author } = Astro.props;
<span class="hljs-keyword">const</span> book = <span class="hljs-string">"Understanding Astro.js"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">data-name</span>=<span class="hljs-string">{book}</span>&gt;</span>A new book<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p>With code fragments referring to changes in a nearby application code, you’ll find an ellipsis to signify no code changes in the previous code, like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ...</span>
&lt;h1 data-name={book}&gt;A changed book name&lt;/h1&gt;
</code></pre>
<p>The code above suggests the previous code block remains the same, except for the new <code>&lt;h1&gt;</code> with <code>A changed book name</code>.</p>
<p>Finally, the book uses the <code>npm</code> package manager. For example, the code to install a package will be described as shown below:</p>
<pre><code class="lang-bash">npm install some-package
</code></pre>
<p>You can use the associated commands for other package managers, such as <code>yarn</code> or <code>pnpm</code>.</p>
<p>Phew! That’s enough housekeeping. Now, let’s dive into Astro!</p>
<h2 id="heading-want-to-get-the-ebook">Want to get the eBook?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/book-cover-transparent-1.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://github.com/understanding-astro/understanding-astro-book">Download ebook on Github</a></em></p>
<ul>
<li>500+ pages of value</li>
<li>4+ practical project chapters</li>
<li>100+ carefully crafted illustrations and images</li>
<li>Learn techniques to build faster applications </li>
<li><strong>Integrate React, Svelte, Vue, Tailwind</strong> and more into an Astro project </li>
<li>Learn to build your own <strong>component islands implementation</strong> from scratch</li>
<li>Learn to <strong>build full stack applications with Astro</strong> (without sacrificing performance) </li>
<li>Go <strong>beyond the basics</strong> and parse Astro code into ASTs and build custom project features </li>
</ul>
<p><a target="_blank" href="https://ohans.me/ua-github">Download the free ebook on GitHub.</a> </p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-133.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chapter one.</em></p>
<h2 id="heading-chapter-1-build-your-first-astro-application">Chapter 1: Build your first Astro Application</h2>
<blockquote>
<p>"Long is the road to learning by precepts, but short and successful by examples." – Seneca the Younger.</p>
</blockquote>
<p>This essay will get started with the basics of Astro by building a practical application: a personal website. To view the complete application, see the <a target="_blank" href="https://github.com/understanding-astro/astro-beginner-project">GitHub repo</a>. </p>
<h2 id="heading-what-youll-learn">What you’ll learn</h2>
<ul>
<li>Build a personal website with Astro.</li>
<li>Set up a local development environment for Astro.</li>
<li>Familiarity with Astro components, layouts, and pages.</li>
<li>A working knowledge of styles and scripts in Astro.</li>
<li>Theming Astro sites via CSS variables.</li>
<li>Leveraging markdown pages for ease.</li>
<li>Deployment of a static Astro application.</li>
</ul>
<h2 id="heading-project-overview">Project Overview</h2>
<p>I remember my first commercial web development project. In retrospect, it was a disaster. One built by a passionate self-taught engineer, but a disaster still.</p>
<p>Let’s make your first Astro project one you’ll remember for good.</p>
<div class="embed-wrapper">
        <iframe width="560" height="315" src="https://www.youtube.com/embed/rshhXm2Q1V0" style="aspect-ratio: 16 / 9; width: 100%; height: auto;" title="YouTube video player" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture; web-share" referrerpolicy="strict-origin-when-cross-origin" allowfullscreen="" loading="lazy"></iframe></div>
<h2 id="heading-getting-started">Getting started</h2>
<p><strong>Astro is a web framework designed for speed</strong>. Before we get to the good stuff, let’s ensure we’re both on the same page.</p>
<h3 id="heading-install-nodejs">Install Node.js</h3>
<p>Firstly, make sure you have Node.js installed.</p>
<p>If you're unsure, run <code>node --version</code> in your terminal. You will get back a Node version if you have Node.js installed.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-29-at-11.11.18@2x.png" alt="Get NodeJS version from the CLI." width="1938" height="720" loading="lazy">
<em>Get NodeJS version from the CLI.</em></p>
<p>Don’t have Node installed? Then, visit the official <a target="_blank" href="https://nodejs.org/en/download">download</a> page and install the necessary package for your operating system. It’s as easy as installing any other computer program. Click, click, click!</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-10.44.30@2x.png" alt="The NodeJS download page." width="2000" height="1517" loading="lazy">
<em>The NodeJS download page.</em></p>
<h3 id="heading-how-to-set-up-your-code-editor">How to set up your code editor</h3>
<p>I’ll avoid any heated debate(s) on what code editor you should be writing software with. Quite frankly, it doesn't matter to me.</p>
<p>However, I use Visual Studio Code (VSCode).</p>
<p>You can develop Astro applications with any code editor, but VSCode is also the officially recommended editor for Astro.</p>
<p>If you’re building with VSCode, install the official <a target="_blank" href="https://marketplace.visualstudio.com/items?itemName=astro-build.astro-vscode">Astro extension</a>. This helps with syntax and semantic highlighting, diagnostic messages, IntelliSense, and more.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-11.03.36@2x.png" alt="The official Astro VSCode extension." width="2206" height="1465" loading="lazy">
<em>The official Astro VSCode extension.</em></p>
<p>Let’s now get started setting up our first Astro project. To do this, we must install Astro. The fastest way to do this is to use the Astro automatic CLI.</p>
<p>To start the install wizard, run the following command:</p>
<pre><code class="lang-bash">npm create astro@latest
</code></pre>
<p>If on <code>pnpm</code> or <code>yarn</code>, the command looks as follows:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># using pnpm</span>
pnpm create astro@latest


<span class="hljs-comment"># using yarn </span>
yarn create astro
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-11.15.44@2x.png" alt="Starting a new project with the Astro CLI wizard." width="2000" height="1548" loading="lazy">
<em>Starting a new project with the Astro CLI wizard.</em></p>
<p>This will start the wizard, which will guide us through helpful prompts. It’s important to mention that we can run this from anywhere on our machine and later choose where exactly we want the project created.</p>
<p>When asked, “Where should we create your new project?” go ahead and pass a file path. In my case, this is <code>documents/dev/books/understanding-astro/astro-beginner-project</code>.</p>
<p>Alternatively, we could have run the <code>npm create astro@latest</code> command in our desired directory and just entered a shorter file path, for example, <code>./astro-beginner-project</code>.</p>
<p>When asked, “How would you like to start your new project?” go ahead and choose “Empty”.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-11.20.54@2x.png" alt="Answering the template CLI prompt." width="2000" height="1548" loading="lazy">
<em>Answering the template CLI prompt.</em></p>
<p>We want a fresh start to explore Astro from the ground up.</p>
<p>Now, we will be asked whether to install dependencies or not. Select yes and hit enter to continue the installation.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-11.22.21@2x.png" alt="Installing dependencies in the CLI prompt." width="2090" height="674" loading="lazy">
<em>Installing dependencies in the CLI prompt.</em></p>
<p>Once the dependencies are installed, answer the “Do you plan to write TypeScript?” prompt with a yes and choose the “strictest” option.</p>
<p>We want strong type safety.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-11.24.22@2x.png" alt="Choosing Typescript in the CLI prompt." width="1538" height="602" loading="lazy">
<em>Choosing Typescript in the CLI prompt.</em></p>
<p>Afterwards, answer the “Initialise a new Git repository?” question with whatever works for you. I’ll go with a yes here and hit enter.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-11.25.33@2x.png" alt="Initialising git in the CLI prompt." width="2000" height="1061" loading="lazy">
<em>Initialising git in the CLI prompt.</em></p>
<p>And voilà! Believe it or not, our new project is already created and ready to go!</p>
<p>Change into the directory where you set up the project. In my case, this looks like the following:</p>
<pre><code class="lang-html">cd ./documents/dev/books/understanding-astro/astro-beginner-project
</code></pre>
<p>And then run the application via the following:</p>
<pre><code class="lang-html">npm run start
</code></pre>
<p>This will start the live application on an available local port 🚀</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-11.29.57@2x.png" alt="The basic Astro project running on localhost:3000" width="1670" height="1332" loading="lazy">
<em>The basic Astro project running on localhost:3000</em></p>
<h2 id="heading-project-structure">Project Structure</h2>
<p>Open the newly created project in your code editor, and you’ll notice that the <code>create astro</code> CLI wizard has included some files and folders.</p>
<p>Astro has an opinionated folder structure. We can see some of this in our new project. By design, every Astro project will include the following in the root directory:</p>
<table>
    <thead>
        <tr>
            <th>
                File / Directory
            </th>
            <th>
                What?
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <br>astro.config.mjs
            </td>
            <td>
                <br>The Astro configuration file. This is where we provide <br>configuration options for our Astro project.<br>
            </td>
        </tr>
        <tr>
            <td>
                <br>tsconfig.json
            </td>
            <td>
                <br>A Typescript configuration file. This specifies the root files and Typescript compiler options.<br>
            </td>
        </tr>
        <tr>
            <td>
                <br>package.json
            </td>
            <td>
                <br>A JSON file that holds the project metadata. <br>This is typically found at the root of most Node.js projects. <br>
            </td>
        </tr>
        <tr>
            <td>
                <br>public/<em></em>
            </td>
            <td>
                <br>This directory holds files and assets that will be copied into <br>the Astro build directory untouched, e.g., fonts, images and <br>files such as <code>robots.txt</code><br>
            </td>
        </tr>
        <tr>
            <td>
                <br>src/<em></em>
            </td>
            <td>
                <br>The source code of our project resides here.<br>
            </td>
        </tr>
    </tbody>
</table>

<p>Let’s now look at the files in our newly generated project.</p>
<h3 id="heading-tsconfigjson-file"><code>tsconfig.json</code> file</h3>
<p>The content of our <code>tsconfig.json</code> file is the following:</p>
<pre><code class="lang-js">{
  <span class="hljs-string">"extends"</span>: <span class="hljs-string">"astro/tsconfigs/strictest"</span>
}
</code></pre>
<p>The <code>extends</code> property points to the base configuration file path to inherit from, that is, inherit the typescript configuration from the file in <code>astro/tsconfigs/strictest</code>.</p>
<p>Using your editor, navigate to the referenced path – for example in <code>vscode</code> by clicking on the link while holding <code>CMD</code>. This will navigate us to <code>node_modules/astro/tsconfigs/strictest.json</code>, where we’ll find a well-annotated file:</p>
<pre><code class="lang-js">{
  ...
  <span class="hljs-string">"compilerOptions"</span>: {
    <span class="hljs-comment">// Report errors for fallthrough cases in switch statements</span>
    <span class="hljs-string">"noFallthroughCasesInSwitch"</span>: <span class="hljs-literal">true</span>,

    <span class="hljs-comment">// Force functions designed to override their parent class to be specified as `override`.</span>
    <span class="hljs-string">"noImplicitOverride"</span>: <span class="hljs-literal">true</span>,

    <span class="hljs-comment">// Force functions to specify that they can return `undefined` if a possible code path does not return a value.</span>
    <span class="hljs-string">"noImplicitReturns"</span>: <span class="hljs-literal">true</span>,
     ...
  }
}
</code></pre>
<p>This is very well annotated, so we won’t spend time on this. But the <code>compilerOptions</code> for TypeScript are set in this file. The point to make here is Astro keeps a list of TypeScript configurations (<code>base</code>, <code>strict</code> and <code>strictest</code>) that our project leverage when we initialise via the CLI wizard.</p>
<p>In this example, we’ll leave the <code>tsconfig.json</code> file as is. TypeScript (and consequently the <code>tsconfig.json</code> file) is optional in Astro projects. But I strongly recommend you leverage TypeScript. We’ll do so all through the book.</p>
<h3 id="heading-packagejson-file"><code>package.json</code> file</h3>
<p>The <code>package.json</code> file is easy to reason about. It holds metadata about our project and includes scripts for managing our Astro project, like <code>npm start</code>, <code>npm run build</code>, and <code>npm preview</code>.</p>
<h3 id="heading-package-lockjson-file"><code>package-lock.json</code> file</h3>
<p>The <code>package-lock.json</code> file is an autogenerated file that holds information on the dependencies/packages for our project. We won’t be touching this file manually. Instead, it is automatically generated (and updated) by npm.</p>
<p>Note that a project’s lock file may differ depending on the package manager, for example yarn or pnpm.</p>
<h3 id="heading-astroconfigmjs-file"><code>astro.config.mjs</code> file</h3>
<p>Most frameworks define a way for us to specify our project-specific configurations. For example, Astro achieves this via the <code>astro.config</code> file.</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'astro/config'</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({});
</code></pre>
<p>At the moment, it defines an empty configuration. So we’ll leave it as is. But this is the right place to specify different build and server options, for example.</p>
<h3 id="heading-srcenvdts-file"><code>src/env.d.ts</code> file</h3>
<p><code>d.ts</code> files are called type declaration files. Yes, that’s for TypeScript alone, and they exist for one purpose: to describe the shape of some existing module. The information in this file is used for type checking by TypeScript.</p>
<pre><code class="lang-js"><span class="hljs-comment">/// &lt;reference types="astro/client" /&gt;</span>
</code></pre>
<p>The content of the file points to <code>astro/client</code>. This is essentially a reference to another declaration file at <code>astro/client.d.ts</code></p>
<h3 id="heading-srcpagesindexastro-file"><code>src/pages/index.astro</code> file</h3>
<p>As mentioned earlier, the <code>src</code> folder is where the source code for our project resides. But what’s the <code>pages</code> directory, and why’s there an <code>index.astro</code> file?</p>
<p>First, consider the contents of the <code>index.astro</code> file:</p>
<pre><code class="lang-js">---
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Astro<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Astro<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>You’ll notice that it looks remarkably similar to standard HTML, with some exceptions.</p>
<p>Also, notice what’s written within the <code>&lt;body&gt;</code> tag: an <code>&lt;h1&gt;</code> element with the text <code>Astro</code>.</p>
<p>If we visit the running application in the browser, we have the <code>&lt;h1&gt;</code> rendered.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-11-at-14.18.20@2x.png" alt="The rendered page heading." width="1808" height="861" loading="lazy">
<em>The rendered page heading.</em></p>
<p>Now change the text to read <code>&lt;h1&gt;Hello world&lt;/h1&gt;</code> and notice how the page is updated in the browser:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-11-at-14.19.41@2x.png" alt="The updated page heading." width="1808" height="872" loading="lazy">
<em>The updated page heading.</em></p>
<p>This leads us nicely to discuss pages in Astro — what I consider the entry point to our application.</p>
<h2 id="heading-introduction-to-astro-pages">Introduction to Astro Pages</h2>
<p>Astro leverages a file-based routing system. It achieves this by using the files in the <code>src/pages</code> directory.</p>
<p>For example, the <code>src/pages/index.astro</code> file corresponds to the <code>index</code> page served in the browser.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-29-at-09.49.26@2x.png" alt="The project’s index page." width="1980" height="1170" loading="lazy">
<em>The project’s index page.</em></p>
<p>Let’s go ahead and create an <code>src/pages/about.astro</code> page with similar content to <code>index.astro</code> as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/about.astro</span>
---
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>About us<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>About us<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<ul>
<li>Copy and paste the exact content of <code>index.astro</code> in <code>about.astro</code>.</li>
<li>Change the <code>&lt;h1&gt;</code> to have the text <code>About us</code>.</li>
</ul>
<p>Now, if we navigate to <code>/about</code> in the browser, we should have the new page rendered.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-29-at-09.50.13@2x.png" alt="The “About us” page." width="1980" height="1170" loading="lazy">
<em>The “About us” page.</em></p>
<h3 id="heading-what-makes-a-valid-astro-page">What makes a valid Astro page?</h3>
<p>We’ve defined Astro pages as files in the <code>src/pages/</code>directory. Unfortunately, this is only partly correct.</p>
<p>For example, if we duplicate the <code>favicon.svg</code> file in <code>public/favicon.svg</code> into the <code>pages</code> directory, does this represent a <code>favicon</code> page?</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-29-at-09.55.21.png" alt="Duplicating the favicon in the pages directory." width="338" height="341" loading="lazy">
<em>Duplicating the favicon in the pages directory.</em></p>
<p>Even though <code>index.astro</code> and <code>about.astro</code> correspond to our website’s index and about pages, <code>/favicon</code> will return a <code>404: Not found</code> error.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-29-at-09.56.51@2x.png" alt="The /favicon route. " width="1980" height="1170" loading="lazy">
<em>The /favicon route.</em></p>
<p>This is because only specific files make a valid astro page. For example, if we consider the <code>index</code> and <code>about</code> files in the <code>pages</code> directory, you perhaps notice something: they both have the <code>.astro</code> file ending!</p>
<p>In layperson’s terms, these are Astro files, but a more technical terminology for these is Astro components.</p>
<p>So, quick quiz: what is an Astro component?</p>
<p>That’s easy—a file with the <code>.astro</code> ending.</p>
<p>10 points to you! Well done.</p>
<h2 id="heading-anatomy-of-an-astro-component">Anatomy of an Astro component</h2>
<p>We’ve established that <code>index.astro</code> and <code>about.astro</code> represent Astro components and are valid Astro pages.</p>
<p>Now, let’s dig into the content of these files.</p>
<p>Consider the contents of the <code>index.astro</code> page:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- removed for brevity --&gt;</span>

<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>Notice the distinction between the two parts of this file’s content.</p>
<p>The section at the bottom contains the page’s markup:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
<span class="hljs-comment">// ... </span>
&lt;html lang=<span class="hljs-string">"en"</span>&gt;
  &lt;!-- removed <span class="hljs-keyword">for</span> brevity --&gt;
&lt;/html&gt;
</code></pre>
<p>This part is called the <strong>component template</strong> section.</p>
<p>While the top section contains a rather strange divider-looking syntax:</p>
<pre><code class="lang-js">---
---
</code></pre>
<p>This part is called the <strong>component script</strong> section, and the <code>---</code> is called a fence.</p>
<p>Together, these make up an Astro component.</p>
<p>Let’s take the component script section for a spin.</p>
<p>The section’s name hints at what this section of the component does. Within the component script code fence, we may declare variables, import packages and fully take advantage of JavaScript or TypeScript.</p>
<p>Oh yes, TypeScript!</p>
<p>Let’s start by creating a variable to hold our user’s profile picture, as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">const</span> profilePicture = <span class="hljs-string">"https://i.imgur.com/JPGFE75.jpg"</span>;
---
</code></pre>
<p>We may then take advantage of the component template section to reference this image as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">const</span> profilePicture = <span class="hljs-string">"https://i.imgur.com/JPGFE75.jpg"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Astro<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- 👀 Look here  --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
      <span class="hljs-attr">src</span>=<span class="hljs-string">{profilePicture}</span>
      <span class="hljs-attr">alt</span>=<span class="hljs-string">"Frau Katerina's headshot."</span>
      <span class="hljs-attr">width</span>=<span class="hljs-string">"100px"</span>
      <span class="hljs-attr">height</span>=<span class="hljs-string">"100px"</span>
    /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>Note that the <code>profilePicture</code> variable is referenced using curly braces <code>{ }</code>. This is how to reference variables from the component script in the component markup.</p>
<p>Now we should have the image rendered on the home page:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-29-at-10.30.54@2x.png" alt="Rendering the user profile photo." width="1980" height="1280" loading="lazy">
<em>Rendering the user profile photo.</em></p>
<p>It’s not much, but it’s honest work, eh?</p>
<p>Let’s go ahead and flesh out the page to have the user’s profile markup:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
<span class="hljs-comment">// ...</span>
  &lt;body&gt;
    &lt;!-- Look here 👀 --&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
        <span class="hljs-attr">src</span>=<span class="hljs-string">{profilePicture}</span>
        <span class="hljs-attr">alt</span>=<span class="hljs-string">"Frau Katerina's headshot."</span>
        <span class="hljs-attr">width</span>=<span class="hljs-string">"100px"</span>
        <span class="hljs-attr">height</span>=<span class="hljs-string">"100px"</span>
      /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Frau Katerina<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>VP of Engineering at Goooogle<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
          Helping developers be excellent and succeed at building scalable
          products
        <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  &lt;/body&gt;
<span class="hljs-comment">// ...</span>
</code></pre>
<p>As you might have noticed, we’re writing <code>HTML</code> looking syntax in the component markup section!</p>
<p>Now we should have the user photo and their bio rendered in the browser as follows:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-10-at-14.07.31@2x.png" alt="The user profile photo and bio." width="2162" height="1498" loading="lazy">
<em>The user profile photo and bio.</em></p>
<h2 id="heading-component-styles">Component Styles</h2>
<p>Styling in Astro is relatively easy to reason about. Add a <code>&lt;style&gt;</code> tag to a component, and Astro will automatically handle its styling.</p>
<p>While it’s possible to select elements directly, let’s go ahead and add classes to the component markup to make this easier:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro  </span>
<span class="hljs-comment">// ...</span>
&lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"profile"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">img</span>
      <span class="hljs-attr">src</span>=<span class="hljs-string">{profilePicture}</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"profile__picture"</span> 
      {/** <span class="hljs-attr">...</span> **/}
    /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"profile__details"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Frau Katerina<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      {/** ... **/}
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/div&gt;
<span class="hljs-comment">// ...</span>
</code></pre>
<p>Add a <code>&lt;style&gt;</code> tag, and write CSS as usual:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ...</span>
&lt;style&gt;
  .profile {
    <span class="hljs-attr">display</span>: flex;
    align-items: flex-start;
    flex-wrap: wrap;
    padding: <span class="hljs-number">1</span>rem <span class="hljs-number">0</span> <span class="hljs-number">3</span>rem <span class="hljs-number">0</span>;
  }

  .profile__details {
    <span class="hljs-attr">flex</span>: <span class="hljs-number">1</span> <span class="hljs-number">0</span> <span class="hljs-number">300</span>px;
  }

  .profile__details &gt; h1 {
    margin-top: <span class="hljs-number">0</span>;
  }

  .profile__picture {
    border-radius: <span class="hljs-number">50</span>%;
    margin: <span class="hljs-number">0</span> <span class="hljs-number">2</span>rem <span class="hljs-number">1</span>rem <span class="hljs-number">0</span>;
  }
&lt;/style&gt;
</code></pre>
<p>The user details should now be styled as expected.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-01-at-08.42.27@2x.png" alt="Applying styles to the index.astro page component." width="1446" height="554" loading="lazy">
<em>Applying styles to the index.astro page component.</em></p>
<p>If we inspect the eventual styles applied to our UI elements via the browser developer tools, we’ll notice that the style selectors look different.</p>
<p>For example, to style the user name, we’ve written the following CSS:</p>
<pre><code class="lang-js">.profile__details &gt; h1 {
  margin-top: <span class="hljs-number">0</span>;
}
</code></pre>
<p>However, what’s applied in the browser looks something like this:</p>
<pre><code class="lang-js">.profile__details:where(.astro-J7PV25F6) &gt; h1:where(.astro-J7PV25F6) {
  margin-top: <span class="hljs-number">0</span>;
}
</code></pre>
<p>Why is this?</p>
<p>The actual style declarations for the <code>h1</code> element remain unchanged. The only difference here is the selector.</p>
<p>The <code>h1</code> element now has auto-generated class names, and the selector is now scoped via the <code>:where</code> CSS selector.</p>
<p>This is done internally by Astro. This makes sure the styles we write don’t leak beyond our component. For example, if we styled every <code>h1</code> in our component as follows:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span> {
  <span class="hljs-attribute">color</span>: red
}
</code></pre>
<p>The eventual style applied in the browser will be similar to the following:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">h1</span><span class="hljs-selector-pseudo">:where(.astro-some-unique-id)</span> {
  <span class="hljs-attribute">color</span>: red
}
</code></pre>
<p>This will ensure all other <code>h1</code> in our project remains the same, and this style only applies to our specific component <code>h1</code>.</p>
<h2 id="heading-page-layouts">Page Layouts</h2>
<p>Look at the pages of our completed application. You may notice that they all have identical forms.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-01-at-09.10.55.png" alt="A breakdown of the application page structure. " width="1171" height="840" loading="lazy">
<em>A breakdown of the application page structure.</em></p>
<p>There’s a navigation bar, a footer, and some container that holds the page’s main content.</p>
<p>Should we repeat these similar UI structures across all pages?</p>
<p>Most people will answer “No”. So, is there a way to share reusable UI structures across pages?</p>
<p>Yes, yes, yes! This is where layouts come in.</p>
<p>Layouts are Astro components with a twist. They are used to provide reusable UI structures across pages, for example navigation bars and footers.</p>
<p>Conventionally, layouts are placed in the <code>src/layouts</code> directory. This is not compulsory but is a widespread pattern.</p>
<p>Let’s go ahead and create our first layout in <code>src/layouts/Main</code>. We’ll do this by moving away all the reusable UI structures currently in <code>index.astro</code> as follows:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Main.astro</span>
---
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>
    {/* Add a new meta description tag */}
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"Frau Katarina's website"</span> /&gt;</span>
    {/* Title is hardcoded as Astro, for now. */}
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Astro<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
      {/* We want the content of each page to go here */}
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<ul>
<li>We’ve moved the <code>&lt;html&gt;</code>, <code>&lt;head&gt;</code> and <code>&lt;body&gt;</code> elements to the <code>Main.astro</code> layout.</li>
<li>We’ve also introduced a new <code>&lt;meta name=description /&gt;</code> tag for SEO.</li>
<li>We’ve equally introduced a <code>&lt;main&gt;</code> element where we want the rest of our page to go in.</li>
<li>Note that the file name of the layout is capitalised, that is <code>Main.astro</code>, not <code>main.astro</code>.</li>
</ul>
<p>On the one hand, layouts are unique because they mostly do one thing: provide reusable structures. But, on the other hand, they aren’t unique. They are like other Astro components and can do everything a component can.</p>
<h2 id="heading-how-to-render-components-and-slots">How to Render Components and Slots</h2>
<p>Rendering an Astro component is similar to how you’d attempt to render an HTML element. For example, we’d render a div by writing the following:</p>
<pre><code class="lang-js">&lt;div&gt;
 render something within the div
&lt;/div&gt;
</code></pre>
<p>The same goes for Astro components.</p>
<p>To render the <code>Main.astro</code> component, we’d do something similar:</p>
<pre><code class="lang-js">&lt;Main&gt;
  render something within the Main component
&lt;/Main&gt;
</code></pre>
<p>Let’s put this into practice. We may now use the <code>Main</code> layout in the <code>index.astro</code> page. To do this, we will do the following:</p>
<ul>
<li>Import the <code>Main</code> layout from <code>"../layouts/Main.astro"</code></li>
<li>Substitute the <code>&lt;html&gt;</code>, <code>&lt;head&gt;</code> and <code>&lt;body&gt;</code> elements for the <code>&lt;Main&gt;</code> layout in <code>index.astro</code>.</li>
</ul>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> Main <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/Main.astro"</span>;

<span class="hljs-keyword">const</span> profilePicture = <span class="hljs-string">"https://i.imgur.com/JPGFE75.jpg"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"profile"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
      <span class="hljs-attr">src</span>=<span class="hljs-string">{profilePicture}</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"profile__picture"</span>
      <span class="hljs-attr">alt</span>=<span class="hljs-string">"Frau Katerina's headshot."</span>
      <span class="hljs-attr">width</span>=<span class="hljs-string">"100px"</span>
      <span class="hljs-attr">height</span>=<span class="hljs-string">"100px"</span>
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"profile__details"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Frau Katerina<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>VP of Engineering at Goooogle<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
        Helping developers be excellent and succeed at building scalable
        products
      <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Main</span>&gt;</span></span>
</code></pre>
<p>If we checked our app, we’d have a blank <code>index</code> page.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-10-at-17.18.07.png" alt="Blank application page. " width="867" height="643" loading="lazy">
<em>Blank application page.</em></p>
<p>Why’s that?</p>
<p>Unlike HTML elements, the child elements in the <code>&lt;Main&gt;</code> tag aren’t automatically rendered.</p>
<pre><code class="lang-js">{<span class="hljs-comment">/** Child div will not be automatically rendered */</span>}
&lt;Main&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Hello from child<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Main</span>&gt;</span></span>
</code></pre>
<p>The <code>&lt;Main&gt;</code> layout component is rendered, and nothing else. The child components aren’t. Hence, the empty page.</p>
<p>To render the child elements of an Astro component, we must specify where to render these using a <code>&lt;slot /&gt;</code> element.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/a.png" alt="Injecting child elements into a slot." width="2000" height="633" loading="lazy">
<em>Injecting child elements into a slot.</em></p>
<p>Let’s add a <code>&lt;slot&gt;</code> within <code>Main.astro</code> :</p>
<pre><code class="lang-js"><span class="hljs-comment">//...</span>
  &lt;body&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
      {/* We want the content of each page to go here */}
       <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span> 
    <span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
  &lt;/body&gt;
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-10-at-17.19.59.png" alt="Page refactored to use a reusable layout component." width="867" height="643" loading="lazy">
<em>Page refactored to use a reusable layout component.</em></p>
<p>We should now have our page rendered with the reusable layout in place.</p>
<h2 id="heading-capitalising-component-names">Capitalising Component Names</h2>
<p>We’ve capitalised the file name of the <code>Main.astro</code> layout component, but is this important?</p>
<p>Theoretically, the answer to that is no.</p>
<p>We could create a file with a lower cased name, for example <code>mainLayout.astro</code> and import the component as follows:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> Main <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/mainLayout.astro"</span>;
</code></pre>
<p>This is perfectly correct.</p>
<p>But where we encounter issues is if we name the imported component with a lowercase:</p>
<pre><code class="lang-js"><span class="hljs-comment">// main NOT Main</span>
<span class="hljs-keyword">import</span> main <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/mainLayout.astro"</span>;
</code></pre>
<p>In this case, we’ll encounter issues when we attempt to render the component, as the name collides with the standard HTML <code>main</code> element.</p>
<p>For this reason, it’s common practice to capitalise both component file names and the imported variable name.</p>
<h2 id="heading-the-global-style-directive">The Global Style Directive</h2>
<p>The <code>Main</code> layout is in place but doesn’t add much to our page. Let’s start by adding some styles for the headers and also centre the page’s content:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/layouts/Main.astro --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">h1</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">3rem</span>;
    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1</span>;
  }

  <span class="hljs-selector-tag">h1</span> + <span class="hljs-selector-tag">h2</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.1rem</span>;
    <span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">1.4rem</span>;
    <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0.9</span>;
    <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">400</span>;
  }

  <span class="hljs-selector-tag">main</span> {
    <span class="hljs-attribute">max-width</span>: <span class="hljs-number">40rem</span>;
    <span class="hljs-attribute">margin</span>: auto;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>With this, we’ll have the <code>main</code> element centred, but the headers, <code>h1</code> and <code>h2</code> remain unstyled.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-10-at-17.21.33.png" alt="A comparison of the changes before and after the layout component style." width="869" height="1056" loading="lazy">
<em>A comparison of the changes before and after the layout component style.</em></p>
<p>This is because styles applied via the <code>&lt;style&gt;</code> tag are locally scoped by default.</p>
<p>Can you tell me why?</p>
<p>The <code>main</code> element resides in the <code>Main</code> layout. But the header <code>h1</code> and <code>h2</code> exist in a different <code>index.astro</code> component.</p>
<p>For our use case, we need global styles.</p>
<p>We need to break out of the default locally scoped styles the Astro component provides, but how do we do this?</p>
<p>Global styles can be a nightmare — except when truly needed. For such cases, Astro provides several solutions. The first is using what’s known as a global style template directive.</p>
<p>I know that sounds like a mouthful! But in simple terms, template directives in Astro are different kinds of HTML attributes that can be used in Astro component templates.</p>
<p>For example, to break out of the default locally scoped <code>&lt;style&gt;</code> behaviour, we can add a <code>is:global</code> attribute as shown below:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">is:global</span>&gt;</span>
 ...
<span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>This will remove the local CSS scoping and make the styles available globally.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-01-at-11.06.50.png" alt="Global styles now inlined in the page via <style>. " width="1213" height="456" loading="lazy">
<em>Global styles now inlined in the page via &lt;style&gt;.</em></p>
<h2 id="heading-custom-fonts-and-global-css">Custom Fonts and Global CSS</h2>
<p>Base layout components like <code>Main.astro</code> are a great place to have global properties such as global styles and custom fonts.</p>
<p>We’ve added global styles via the <code>is:global</code> template directive. But alternatively, we could have all global styles imported into <code>Main.astro</code> from a <code>global.css</code> file.</p>
<p>In cases where a project requires importing some existing global css file, this is the more straightforward approach.</p>
<p>For example, let’s refactor our project to use <code>global.css</code>. To do so, move the entire CSS content within the <code>&lt;style is:global&gt;</code> element into <code>src/styles/global.css</code>. Then import the styles in the <code>Main.astro</code> component frontmatter:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Main.astro</span>
---
<span class="hljs-keyword">import</span> <span class="hljs-string">"../styles/global.css"</span>;
---
</code></pre>
<p>This will load and inject style onto the page.</p>
<p>Now, let’s turn our attention to global fonts.</p>
<p>We will use the Google <a target="_blank" href="https://fonts.google.com/specimen/Inter">Inter</a> font for the project, but how do we do this?</p>
<p>Technically speaking, to add Inter to our project, we must add the <code>&lt;link&gt;</code>s to Inter on every page required.</p>
<p>But instead of repeating ourselves on every page, we can leverage the shared <code>Main.astro</code> layout component.</p>
<p>Go ahead and add the <code>&lt;link&gt;</code>s to the Inter font as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Main.astro</span>
&lt;html lang=<span class="hljs-string">"en"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    {/** 👀 Look here ... */}
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"preconnect"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"preconnect"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.gstatic.com"</span> <span class="hljs-attr">crossorigin</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span>
      <span class="hljs-attr">href</span>=<span class="hljs-string">"https://fonts.googleapis.com/css2?family=Inter:wght@400;500;700&amp;display=swap"</span>
      <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span>
    /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span></span>
  {<span class="hljs-comment">/** ... */</span>}
&lt;/html&gt;
</code></pre>
<p>We may now update the <code>global.css</code> file to use the new font family:</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">body</span> {
  <span class="hljs-attribute">font-family</span>: <span class="hljs-string">"Inter"</span>, sans-serif;
  <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span> <span class="hljs-number">0.5rem</span>; <span class="hljs-comment">/* Additional body style */</span>
}
</code></pre>
<p>And boom! We have sorted global fonts.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-10-at-17.41.13.png" alt="The page with global fonts and styles. " width="867" height="566" loading="lazy">
<em>The page with global fonts and styles.</em></p>
<h2 id="heading-independent-astro-components">Independent Astro Components</h2>
<p>We’ve discussed two special types of Astro components: layouts and pages.</p>
<p>But a working site is made up of more than just layouts and pages. For example, different blocks of user interfaces are typically embedded within a page. These independent and reusable blocks of user interfaces can also be represented using Astro components.</p>
<p>Let’s put this into practice by creating <code>NavigationBar</code> and <code>Footer</code> components to be used in the <code>Main.astro</code> layout.</p>
<p>When creating components, a standard convention is to have them in the <code>src/components</code> directory. Let’s go ahead and create one.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/Footer.astro</span>
&lt;footer&gt;&amp;copy; Frau Katerina&lt;/footer&gt;

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">footer</span> {
    <span class="hljs-comment">/* Applies top and bottom paddings */</span>
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">3rem</span> <span class="hljs-number">0</span>;
    <span class="hljs-comment">/* Centers the text content */</span>
    <span class="hljs-attribute">text-align</span>: center;
    <span class="hljs-comment">/* Makes the font smaller */</span>
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">0.9rem</span>;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre>
<p>Let’s also create a <code>NavigationBar</code> component:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/NavigationBar.astro</span>
---
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
      {/** Link points nowhere for now*/}
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Philosophies<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
      {/** Link points nowhere for now*/}
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"#"</span>&gt;</span>Beyond technology<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">nav</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">align-items</span>: flex-start;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span> <span class="hljs-number">0</span>;
  }

  <span class="hljs-selector-tag">ul</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-wrap</span>: wrap;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span> auto <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  }

  <span class="hljs-selector-tag">nav</span> <span class="hljs-selector-tag">li</span> {
    <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0.8</span>;
    <span class="hljs-attribute">list-style</span>: none;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">0.95rem</span>;
  }

  <span class="hljs-selector-tag">a</span> {
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5rem</span> <span class="hljs-number">1rem</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">text-decoration</span>: none;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre>
<p>Now render the <code>NavigationBar</code> and <code>Footer</code> as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Main.astro</span>
---
<span class="hljs-comment">//...</span>
<span class="hljs-keyword">import</span> Footer <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Footer.astro"</span>;
<span class="hljs-keyword">import</span> NavigationBar <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/NavigationBar.astro"</span>;
---

{<span class="hljs-comment">/** ... **/</span>}
&lt;main&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">NavigationBar</span> /&gt;</span></span>

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span></span>

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Footer</span> /&gt;</span></span>
&lt;/main&gt;
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-01-at-15.17.48@2x.png" alt="Navigation bar and footer rendered. " width="1758" height="929" loading="lazy">
<em>Navigation bar and footer rendered.</em></p>
<h2 id="heading-how-to-add-interactive-scripts">How to Add Interactive Scripts</h2>
<p>An integral part of Astro’s philosophy is shipping zero JavaScript by default to the browser.</p>
<p>This means our pages get compiled into <code>HTML</code> pages with all JavaScript stripped away by default.</p>
<p>You might ask, what about all the JavaScript written in the component script section of an Astro component?</p>
<p>The component script and markup will be used to generate the eventual <code>HTML</code> page(s) sent to the browser.</p>
<p>For example, go ahead and add a simple <code>console.log</code> to the frontmatter of the <code>index.astro</code> page:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello world!"</span>);
---
</code></pre>
<p>Inspect the browser console and notice how the log never makes it to the browser!</p>
<p>So, where’s the log?</p>
<p>Astro runs on the server. In our case, this represents our local development server. So, the <code>console.log</code> will appear in the terminal where Astro serves our local application.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-01-at-17.55.33.png" alt="Astro server logs." width="496" height="127" loading="lazy">
<em>Astro server logs.</em></p>
<p>When we eventually build our application for production with <code>npm run build</code>, Astro will output <code>HTML</code> files corresponding to our pages in <code>src/pages</code>.</p>
<p>In this example, the <code>Hello world!</code> message will be logged but not get into the compiled <code>HTML</code> pages.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-01-at-18.02.53.png" alt="Logs during building the production application." width="608" height="362" loading="lazy">
<em>Logs during building the production application.</em></p>
<p>To add interactive scripts, that is scripts that make it into the final <code>HTML</code> page build output, add a <code>&lt;script&gt;</code> element in the component markup section.</p>
<p>For example, let’s move the <code>console.log</code> from the frontmatter to the markup via a <code>&lt;script&gt;</code> element:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
--- 
<span class="hljs-comment">// ...</span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello world!"</span>);
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>We should have <code>Hello world!</code> logged in the browser console:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-01-at-18.07.13@2x.png" alt="The browser “Hello world”\ log." width="1758" height="914" loading="lazy">
<em>The browser “Hello world” log.</em></p>
<h2 id="heading-interactive-theme-toggle">Interactive Theme Toggle</h2>
<p>Let’s put our newly found knowledge of client-side scripts to good use.</p>
<p>Create a new <code>ThemeToggler.astro</code> component in the <code>src/components</code> directory.</p>
<p>Add the following markup:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/ThemeToggler.astro</span>
&lt;button aria-label=<span class="hljs-string">"Theme toggler"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">width</span>=<span class="hljs-string">"25px"</span> <span class="hljs-attr">xmlns</span>=<span class="hljs-string">"http://www.w3.org/2000/svg"</span> <span class="hljs-attr">viewBox</span>=<span class="hljs-string">"0 0 24 24"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"sun"</span>
      <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">"evenodd"</span>
      <span class="hljs-attr">d</span>=<span class="hljs-string">"M12 17.5a5.5 5.5 0 1 0 0-11 5.5 5.5 0 0 0 0 11zm0 1.5a7 7 0 1 0 0-14 7 7 0 0 0 0 14zm12-7a.8.8 0 0 1-.8.8h-2.4a.8.8 0 0 1 0-1.6h2.4a.8.8 0 0 1 .8.8zM4 12a.8.8 0 0 1-.8.8H.8a.8.8 0 0 1 0-1.6h2.5a.8.8 0 0 1 .8.8zm16.5-8.5a.8.8 0 0 1 0 1l-1.8 1.8a.8.8 0 0 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM6.3 17.7a.8.8 0 0 1 0 1l-1.7 1.8a.8.8 0 1 1-1-1l1.7-1.8a.8.8 0 0 1 1 0zM12 0a.8.8 0 0 1 .8.8v2.5a.8.8 0 0 1-1.6 0V.8A.8.8 0 0 1 12 0zm0 20a.8.8 0 0 1 .8.8v2.4a.8.8 0 0 1-1.6 0v-2.4a.8.8 0 0 1 .8-.8zM3.5 3.5a.8.8 0 0 1 1 0l1.8 1.8a.8.8 0 1 1-1 1L3.5 4.6a.8.8 0 0 1 0-1zm14.2 14.2a.8.8 0 0 1 1 0l1.8 1.7a.8.8 0 0 1-1 1l-1.8-1.7a.8.8 0 0 1 0-1z"</span>
    &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">path</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"moon"</span>
      <span class="hljs-attr">fill-rule</span>=<span class="hljs-string">"evenodd"</span>
      <span class="hljs-attr">d</span>=<span class="hljs-string">"M16.5 6A10.5 10.5 0 0 1 4.7 16.4 8.5 8.5 0 1 0 16.4 4.7l.1 1.3zm-1.7-2a9 9 0 0 1 .2 2 9 9 0 0 1-11 8.8 9.4 9.4 0 0 1-.8-.3c-.4 0-.8.3-.7.7a10 10 0 0 0 .3.8 10 10 0 0 0 9.2 6 10 10 0 0 0 4-19.2 9.7 9.7 0 0 0-.9-.3c-.3-.1-.7.3-.6.7a9 9 0 0 1 .3.8z"</span>
    &gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">path</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">svg</span>&gt;</span></span>
&lt;/button&gt;
</code></pre>
<ul>
<li>For accessibility, the button has an <code>aria-label</code> of <code>Theme toggler</code>.</li>
<li>The <code>SVG</code> has a fixed width of <code>25px</code>, rendering two <code>&lt;path&gt;</code> elements.</li>
<li>The first <code>&lt;path&gt;</code> visually represents a sun icon. The second is a moon icon.</li>
<li>By default, both icons (sun and moon) are rendered. Our goal is to toggle the displayed icon based on the active theme.</li>
</ul>
<p>Then import the component and render it in the <code>NavigationBar</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/NavigationBar</span>
---
<span class="hljs-keyword">import</span> ThemeToggler <span class="hljs-keyword">from</span> <span class="hljs-string">"./ThemeToggler.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">nav</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
    {/** ... **/}
  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>
  {/** 👀 Look here **/}
  <span class="hljs-tag">&lt;<span class="hljs-name">ThemeToggler</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">nav</span>&gt;</span></span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-02-at-06.43.28.png" alt="The sun and moon icons rendered in the toggle button." width="787" height="459" loading="lazy">
<em>The sun and moon icons rendered in the toggle button.</em></p>
<p>Let’s add some <code>&lt;style&gt;</code> to <code>ThemeToggler</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/ThemeToggler.astro</span>
<span class="hljs-comment">// ... </span>
&lt;style&gt;
  button {
    <span class="hljs-attr">cursor</span>: pointer;
    border-radius: <span class="hljs-number">10</span>px;
    border: <span class="hljs-number">0</span>;
    padding: <span class="hljs-number">5</span>px <span class="hljs-number">10</span>px;
    transition: all <span class="hljs-number">0.2</span>s ease-<span class="hljs-keyword">in</span>-out;
  }

  <span class="hljs-attr">button</span>:hover {
    <span class="hljs-comment">/* Make the button smaller (scale down) when hovered */</span>
    <span class="hljs-attr">transform</span>: scale(<span class="hljs-number">0.9</span>);
  }

  <span class="hljs-attr">button</span>:active {
    <span class="hljs-comment">/** Return the button to its standard size when active */</span>
    <span class="hljs-attr">transform</span>: scale(<span class="hljs-number">1</span>);
  }

  .sun {
    <span class="hljs-comment">/* Hide the sun icon by default. This assumes a light theme by default */</span>
    <span class="hljs-attr">fill</span>: transparent;
  }
&lt;/style&gt;
</code></pre>
<p>Now, we should have a decent-looking theme toggler.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-02-at-06.50.49.png" alt="A styled theme toggle button." width="925" height="205" loading="lazy">
<em>A styled theme toggle button.</em></p>
<h2 id="heading-the-global-selector">The <code>:global()</code> Selector</h2>
<p>Let’s take a moment to consider the strategy we’ll use for toggling the theme.</p>
<p>We’ll toggle a CSS class on the root element whenever a user clicks the toggle.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/embed.png" alt="Adding a new “dark” class on toggle." width="2000" height="1254" loading="lazy">
<em>Adding a new “dark” class on toggle.</em></p>
<p>For example, if the user was viewing the site in light mode and clicked to toggle, we’ll add a <code>.dark</code> class to the root element and, based on that, apply dark-themed styles.</p>
<p>If the user is in dark mode, clicking the toggle will remove the <code>.dark</code> class. We’ll refer to this as a class strategy for toggling dark mode.</p>
<p>Based on this strategy, we must update our local <code>ThemeToggler</code> style to display the relevant icon depending on the global <code>.dark</code> class.</p>
<p>To do this, we will leverage the <code>:global</code> selector.</p>
<p>Here’s how we’d achieve this:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/components/ThemeToggler.astro --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
 <span class="hljs-comment">/**...**/</span>

 <span class="hljs-comment">/** If a parent element has a .dark class, target the .sun icon and make the path black (shows the icon) */</span>
 <span class="hljs-selector-pseudo">:global(.dark)</span> <span class="hljs-selector-class">.sun</span> {
   <span class="hljs-attribute">fill</span>: black;
 }

 <span class="hljs-comment">/** If a parent element has a .dark class, target the .moon icon and make the path transparent (hides the icon) */</span>
 <span class="hljs-selector-pseudo">:global(.dark)</span> <span class="hljs-selector-class">.moon</span> {
   <span class="hljs-attribute">fill</span>: transparent;
 }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>To see this at work, inspect the page via the developer tools, and add a <code>dark</code> class to the root element. The toggle icon will be appropriately changed.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-02-at-07.03.08.png" alt="Inspecting icon change with a root dark class." width="1032" height="170" loading="lazy">
<em>Inspecting icon change with a root dark class.</em></p>
<p>In practice, limit <code>:global</code> only to appropriate use cases, because mixing global and locally scoped component styles will become challenging to debug. But this is permissible, given our use case.</p>
<h2 id="heading-event-handling">Event Handling</h2>
<p>We’ve handled the styles for our toggle, assuming a <code>.dark</code> root class. Now, let’s go ahead and handle the toggle click event with a <code>&lt;script&gt;</code> element.</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/components/ThemeToggler.astro --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-comment">/** Represent the toggle theme class with a variable */</span>
  <span class="hljs-keyword">const</span> DARK_THEME_CLASS = <span class="hljs-string">"dark"</span>;

  <span class="hljs-comment">/** Grab the toggle */</span>
  <span class="hljs-keyword">const</span> toggle = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"button"</span>);
  <span class="hljs-comment">/** Grab the document root element. In this case &lt;html&gt;  */</span>
  <span class="hljs-keyword">const</span> rootEl = <span class="hljs-built_in">document</span>.documentElement;

  <span class="hljs-keyword">if</span> (toggle) {
    toggle.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">/** toggle the "dark" class on the root element */</span>
      rootEl.classList.toggle(DARK_THEME_CLASS);
    });
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Notice that this is standard JavaScript. Nothing fancy going on here.</p>
<ul>
<li>The toggle is selected via <code>document.querySelector("button")</code>.</li>
<li>To set up an event listener, we use the <code>.addEventListener</code> method on the button.</li>
<li>On clicking the button, we toggle the class list on the root element: adding or removing the “dark” class.</li>
</ul>
<p>With this in place, the toggle icon changes when clicked to either that of the sun or moon.</p>
<p>Excellent!</p>
<h2 id="heading-theming-via-css-variables">Theming via CSS Variables</h2>
<p>CSS variables are outstanding, and we’ll leverage them for theming our application.</p>
<p>Firstly, let’s go ahead and define the colour variables we’ll use in the project.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 styles/global.css</span>
html {
  --background: white;
  --grey<span class="hljs-number">-200</span>: #<span class="hljs-number">222222</span>;
  --grey<span class="hljs-number">-400</span>: #<span class="hljs-number">444444</span>;
  --grey<span class="hljs-number">-600</span>: #<span class="hljs-number">333333</span>;
  --grey<span class="hljs-number">-900</span>: #<span class="hljs-number">111111</span>;
}

html.dark {
  --background: black;
  --grey<span class="hljs-number">-200</span>: #eaeaea;
  --grey<span class="hljs-number">-400</span>: #acacac;
  --grey<span class="hljs-number">-600</span>: #ffffff;
  --grey<span class="hljs-number">-900</span>: #fafafa;
}
</code></pre>
<ul>
<li>Set the variables on the root <code>HTML</code> element to be globally scoped.</li>
<li>A CSS variable is a property that begins with two dashes, <code>--</code>  – for example <code>--background</code>.</li>
<li>For simplicity, we’ll stick to the minimal grey palette above.</li>
</ul>
<p>The first visual change we’ll make is to add the following <code>color</code> and <code>background</code> style declarations to the <code>body</code> element:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 styles/global.css</span>
body {
  <span class="hljs-attr">color</span>: <span class="hljs-keyword">var</span>(--grey<span class="hljs-number">-600</span>);
  background: <span class="hljs-keyword">var</span>(--background);
}
</code></pre>
<p>With this seemingly simple change, we should now have the text and background colour of the <code>body</code> react to clicking the toggle.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-02-at-07.51.51.png" alt="Dark mode activated. " width="766" height="428" loading="lazy">
<em>Dark mode activated.</em></p>
<p>Finally, update the navigation links in <code>NavigationBar</code> to reflect theme preferences:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* 📂 src/components/NavigationBar.astro */</span>
&lt;<span class="hljs-selector-tag">style</span>&gt;
  <span class="hljs-comment">/* ... */</span>
  <span class="hljs-selector-tag">a</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--grey-<span class="hljs-number">400</span>);
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">0.5rem</span> <span class="hljs-number">1rem</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">text-decoration</span>: none;
  }

  <span class="hljs-selector-tag">a</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--grey-<span class="hljs-number">900</span>);
  }
&lt;/<span class="hljs-selector-tag">style</span>&gt;
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-02-at-07.55.56.png" alt="Navigation links styled for dark mode." width="792" height="458" loading="lazy">
<em>Navigation links styled for dark mode.</em></p>
<h2 id="heading-how-to-access-global-client-objects">How to Access Global Client Objects</h2>
<p>Question! 🙋🏼</p>
<p>Where should we access global objects such as <code>window.localStorage</code>? Within an Astro component frontmatter or an interactive <code>&lt;script&gt;</code>?</p>
<p>At this point, I hope the answer to the question is clear from previous examples.</p>
<p>Since Astro runs on the server, attempting to access a <code>window</code> property within the frontmatter of a component will result in an error.</p>
<pre><code class="lang-css"><span class="hljs-selector-tag">---</span>
{<span class="hljs-comment">/** ❌ this will fail with the error: window is undefined **/</span>}
 <span class="hljs-selector-tag">const</span> <span class="hljs-selector-tag">value</span> = <span class="hljs-selector-tag">window</span><span class="hljs-selector-class">.localStorage</span><span class="hljs-selector-class">.getItem</span>("<span class="hljs-selector-tag">value</span>")
<span class="hljs-selector-tag">---</span>
</code></pre>
<p>To access <code>window</code> properties, we need the script to run on the client – that is, in the browser. So, we must leverage one or more client-side scripts.</p>
<p>A good use case for this is remembering the user’s theme choice.</p>
<p>If users toggle their theme from light to dark and refresh the browser, they lose the selected theme state.</p>
<p>How about we save this state to the browser’s local storage and restore the selected theme upon refresh?</p>
<p>Well, let’s do that!</p>
<p>Here are the first steps we’ll take:</p>
<ul>
<li>Grab the current state of the theme, that is dark or light, when the theme toggle is clicked.</li>
<li>Save the theme value to the browser’s local storage in the form: </li>
</ul>
<pre><code>{
  <span class="hljs-attr">COLOUR_MODE</span>: <span class="hljs-string">"LIGHT"</span> | <span class="hljs-string">"DARK"</span>    
}
</code></pre><p>Here’s that translated in code:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/components/ThemeToggler.astro --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">const</span> DARK_THEME_CLASS = <span class="hljs-string">"dark"</span>;
  <span class="hljs-comment">/** Represent the local storage key by a variable */</span>
  <span class="hljs-keyword">const</span> COLOUR_MODE = <span class="hljs-string">"COLOUR_MODE"</span>;
  <span class="hljs-comment">/** Represent the local storage values by variables */</span>
  <span class="hljs-keyword">const</span> LIGHT_THEME = <span class="hljs-string">"LIGHT"</span>;
  <span class="hljs-keyword">const</span> DARK_THEME = <span class="hljs-string">"DARK"</span>;
  <span class="hljs-comment">/** ... **/</span>
  toggle.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">/** ... */</span>
    <span class="hljs-comment">/**Get the current theme mode, i.e., light or dark */</span>
    <span class="hljs-keyword">const</span> colourMode = rootEl.classList.contains(DARK_THEME_CLASS)
      ? DARK_THEME
      : LIGHT_THEME;

    <span class="hljs-comment">/** Save the current theme to local storage   */</span>
    <span class="hljs-built_in">window</span>.localStorage.setItem(COLOUR_MODE, colourMode);
  });
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>We have saved the theme to local storage but must now set the active theme as soon as the page is loaded and the <code>script</code> is executed.</p>
<p>Here’s the annotated code required to achieve this:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/components/ThemeToggler.astro --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  {<span class="hljs-comment">/**... **/</span>}
  <span class="hljs-keyword">const</span> getInitialColourMode = <span class="hljs-function">() =&gt;</span> {
    <span class="hljs-comment">/** Get colour mode from local storage **/</span>
    <span class="hljs-keyword">const</span> previouslySavedColourMode = <span class="hljs-built_in">window</span>.localStorage.getItem(COLOUR_MODE);
    <span class="hljs-keyword">if</span> (previouslySavedColourMode) {
      <span class="hljs-keyword">return</span> previouslySavedColourMode;
    }
    <span class="hljs-comment">/** Does the user prefer dark mode, e.g., through an operating system or user agent setting? */</span>
    <span class="hljs-keyword">if</span> (<span class="hljs-built_in">window</span>.matchMedia(<span class="hljs-string">"(prefers-color-scheme: dark)"</span>).matches) {
      <span class="hljs-keyword">return</span> DARK_THEME;
    }
    <span class="hljs-comment">/** Default to the light theme */</span>
    <span class="hljs-keyword">return</span> LIGHT_THEME;
  };
  <span class="hljs-comment">/**Get initial colour mode */</span>
  <span class="hljs-keyword">const</span> initialColourMode = getInitialColourMode();
  <span class="hljs-keyword">const</span> setInitialColourMode = <span class="hljs-function">(<span class="hljs-params">mode: string</span>) =&gt;</span> {
    <span class="hljs-keyword">if</span> (mode === LIGHT_THEME) {
      rootEl.classList.remove(DARK_THEME_CLASS);
    } <span class="hljs-keyword">else</span> {
      rootEl.classList.add(DARK_THEME_CLASS);
    }
  };
  <span class="hljs-comment">/** Set the initial colour mode as soon as the script is executed */</span>
  setInitialColourMode(initialColourMode);
{<span class="hljs-comment">/**... **/</span>}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Now, give this a try. First, toggle the theme and refresh to see the theme choice preserved.</p>
<h2 id="heading-the-magic-of-scripts">The Magic of Scripts</h2>
<p>Client-side scripts added via a <code>&lt;script&gt;</code> may seem like your typical vanilla JavaScript, but they’re more capable in specific ways.</p>
<p>The most crucial point is that Astro processes these. This means within a <code>&lt;script&gt;</code>, we can import other scripts or import npm packages, and Astro will resolve and package the script for use in the browser.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
 <span class="hljs-comment">/** ✅ valid package import **/</span>
 <span class="hljs-keyword">import</span> { titleCase } <span class="hljs-keyword">from</span> <span class="hljs-string">"title-case"</span>;

 <span class="hljs-keyword">const</span> title = titleCase(<span class="hljs-string">"string"</span>) 

 alert(title)
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<pre><code class="lang-html">/** ✅ valid script reference **/
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"path-to-script.js"</span>/&gt;</span>
</code></pre>
<p>Another critical point is the <code>&lt;script&gt;</code> fully supports TypeScript. For example, in our solution, we typed the parameter for the <code>setInitialColourMode</code> function:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// mode is of type string </span>
<span class="hljs-keyword">const</span> setInitialColourMode = <span class="hljs-function">(<span class="hljs-params">mode: <span class="hljs-built_in">string</span></span>) =&gt;</span> {
  ...
};
</code></pre>
<p>We don’t have to sacrifice type safety within the client <code>&lt;script&gt;</code> elements and can go on to write standard TypeScript code. Astro will strip out the types at build time and only serve the processed JavaScript to the browser.</p>
<p>Here’s a summary of what Astro does:</p>
<ul>
<li><code>NPM</code> packages and local files can be imported and will be bundled.</li>
<li>TypeScript is fully supported within the <code>&lt;script&gt;</code>.</li>
<li>If a single <code>Astro</code> component with a <code>&lt;script&gt;</code> is used multiple times on a page, the <code>&lt;script&gt;</code> is processed and only included once.</li>
<li>Astro will process and insert the script in the <code>&lt;head&gt;</code> of the page with a <code>type=module</code> attribute.</li>
<li>❗️The implication of <code>type=module</code> is that the browser will defer the script, that is load in parallel and <strong>execute it only after</strong> the page’s parsed.</li>
</ul>
<h2 id="heading-how-to-leverage-inline-scripts">How to Leverage Inline Scripts</h2>
<p>By default, Astro processes <code>&lt;script&gt;</code>s. However, to opt out of Astro’s default script processing, we may pass a <code>is:inline</code> directive as shown below:</p>
<pre><code class="lang-ts">&lt;script is:inline&gt; 
 <span class="hljs-comment">// Imports will not be processed </span>
 <span class="hljs-comment">// Typescript not supported by default </span>
 <span class="hljs-comment">// Script will be added as is, e.g., multiple times if the component is used more than once on a page. </span>
&lt;/script&gt;
</code></pre>
<p>In the real world, we quickly realise that the defaults don’t always satisfy every project requirement.</p>
<p>For example, consider the un-styled flash of incorrect theme when we refresh our home page. For a user who chose the dark theme previously, refreshing the page shows light-themed rendered content before changing to dark after the script is parsed.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-03-at-03.24.42.png" alt="Transitioning light themed content viewed on Regular 3G throttling." width="773" height="444" loading="lazy">
<em>Transitioning light themed content viewed on Regular 3G throttling.</em></p>
<p>This occurs because we restore the user-chosen theme only after the page’s HTML has been parsed, that is the default behaviour of processed Astro scripts.</p>
<p>To prevent this, we will use the <code>is:inline</code> directive, which will make the script blocking, that is, it'll be executed immediately and stops parsing until completed.</p>
<p>Since scripts with the <code>is:inline</code> attribute aren’t processed, they’ll be added multiple times if used in reusable components that appear more than once on the page.</p>
<p>So, let’s go ahead and move the theme restoration code bit into <code>Main.astro</code> — because the <code>Main</code> layout is only included once per page.</p>
<p>We’ll also make sure to add this within the <code>&lt;head&gt;</code> of the layout, as shown below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/layouts/Main.astro --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span> 
   <span class="hljs-comment">&lt;!-- ... --&gt;</span>    
    <span class="hljs-comment">&lt;!-- 👀 add is:inline --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">is:inline</span>&gt;</span><span class="javascript">
      <span class="hljs-keyword">const</span> DARK_THEME_CLASS = <span class="hljs-string">"dark"</span>;
      <span class="hljs-keyword">const</span> COLOUR_MODE = <span class="hljs-string">"COLOUR_MODE"</span>;
      <span class="hljs-keyword">const</span> LIGHT_THEME = <span class="hljs-string">"LIGHT"</span>;
      <span class="hljs-keyword">const</span> DARK_THEME = <span class="hljs-string">"DARK"</span>;
      <span class="hljs-keyword">const</span> rootEl = <span class="hljs-built_in">document</span>.documentElement;
      <span class="hljs-keyword">const</span> getInitialColourMode = <span class="hljs-function">() =&gt;</span> {
        <span class="hljs-comment">/** ... */</span>
      }
      <span class="hljs-keyword">const</span> initialColourMode = getInitialColourMode();
      <span class="hljs-comment">// 👀 remove string type on mode </span>
      <span class="hljs-keyword">const</span> setInitialColourMode = <span class="hljs-function">(<span class="hljs-params">mode</span>) =&gt;</span> {
         <span class="hljs-comment">/** ... */</span>
      };
      <span class="hljs-comment">/** Set the initial colour mode as soon as the script is executed */</span>
      setInitialColourMode(initialColourMode);
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
</code></pre>
<p>We’re explicitly adding this to the <code>&lt;head&gt;</code> because Astro will not process the <code>is:inline</code> script. As such, it won’t be moved to the <code>head</code> by Astro.</p>
<p>Be careful with <code>is:inline</code> as it removes the default non-blocking nature of scripts. But it’s ideal for this use case.</p>
<p>Open your developer tools and throttle the network. Then go ahead and refresh after toggling dark mode. We should have eradicated the flash of incorrect theme:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-11-at-07.30.21@2x.png" alt="Throttling the network via the chrome developer tools." width="2451" height="1063" loading="lazy">
<em>Throttling the network via the chrome developer tools.</em></p>
<h2 id="heading-global-selectors-in-scripts">Global Selectors in Scripts</h2>
<p>Understanding how Astro processes the <code>&lt;script&gt;</code> in our components helps us make informed decisions.</p>
<p>We know the <code>&lt;script&gt;</code> will eventually be bundled and injected into our page’s <code>&lt;head&gt;</code>.</p>
<p>But consider our selector for registering the theme toggle clicks:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// 📂 src/components/ThemeToggler.astro </span>
<span class="hljs-keyword">const</span> toggle = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"button"</span>);
</code></pre>
<p>The problem with this seemingly harmless code is that <code>document.querySelector</code> will return the first element that matches the selector — a button element.</p>
<p>This will be selected if we add a random button somewhere on the page before our theme toggle button.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Main.astro</span>
&lt;button&gt; Donate to charity &lt;/button&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Nav</span> /&gt;</span></span>

<span class="hljs-comment">//...</span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-03-at-03.38.21.png" alt="The donate to charity button." width="990" height="704" loading="lazy">
<em>The donate to charity button.</em></p>
<p>This button, which has nothing to do with theme toggling, will now be responsible for toggling the user’s theme.</p>
<p>Clicking “donate to charity” now toggles the theme. This is unacceptable.</p>
<p>The lesson here is to be mindful of your DOM selectors and be specific where possible, for example via ids or classes:</p>
<pre><code class="lang-js"><span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"#some-unique-id"</span>)
</code></pre>
<p>Let’s refactor our solution to use a data attribute.</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/components/ThemeToggler.astro --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">aria-label</span>=<span class="hljs-string">"Theme toggler"</span> <span class="hljs-attr">data-theme-toggle</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- ... --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-comment">/** 👀 Look here */</span>
  <span class="hljs-keyword">const</span> toggle = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">"[data-theme-toggle]"</span>);
  <span class="hljs-comment">// ... </span>
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>With the more specific selector, only an element with the data attribute <code>theme-toggle</code> will be selected, leaving <code>&lt;button&gt; Donate to charity &lt;/button&gt;</code> out of our theme toggle business.</p>
<h2 id="heading-markdown-pages">Markdown Pages</h2>
<p>We’ve established that not all file types are valid pages in Astro. We’ve seen Astro components as pages, but allow me to introduce markdown pages.</p>
<p>Markdown is a popular, easy-to-use markup language for creating formatted text. I’m sure my nan does not know markdown, so it’s safer to say it’s a famous text format among developers.</p>
<p>It’s no surprise Astro supports creating pages via markdown. So, let’s put this to the test.</p>
<p>We’ll create two new pages to replace our dead <code>Philosophies</code> and <code>Beyond technology</code> navigation links.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-02-at-10.50.19@2x.png" alt="The dead navigation links." width="1490" height="260" loading="lazy">
<em>The dead navigation links.</em></p>
<p>Create the first page in <code>src/pages/philosophies.md</code> with the following content:</p>
<pre><code class="lang-md"><span class="hljs-bullet">-</span> Be present and enjoy the now
<span class="hljs-bullet">-</span> Be driven by values
<span class="hljs-bullet">-</span> Health is wealth
<span class="hljs-bullet">-</span> Be deliberate
<span class="hljs-bullet">-</span> Laugh out loud
</code></pre>
<p>Create the second page in <code>src/pages/beyond-tech.md</code> with the following content:</p>
<pre><code class="lang-md"><span class="hljs-bullet">-</span> 5X Marathoner
<span class="hljs-bullet">-</span> Olympic gold medalist
<span class="hljs-bullet">-</span> Fashion model
<span class="hljs-bullet">-</span> Michellin star restaurant owner
<span class="hljs-bullet">-</span> Adviser to the vice president
</code></pre>
<p>These files are written in markdown syntax.</p>
<p>As with Astro component pages, markdown pages eventually get compiled to standard <code>HTML</code> pages rendered in the browser. The same file-based routing is also used. For example, to access the <code>philosophies</code> and <code>beyond-tech</code> pages, visit the <code>/philosophies</code> and <code>/beyond-tech</code>  routes, respectively.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-03-at-02.42.23.png" alt="The philosophies page" width="990" height="567" loading="lazy">
<em>The philosophies page</em></p>
<h2 id="heading-how-to-navigate-between-pages">How to Navigate Between Pages</h2>
<p>Navigating between pages in Astro requires no magic wand. Surprise!</p>
<p>Astro uses the standard <code>&lt;a&gt;</code> element to navigate between pages. This makes sense as each page is a separate <code>HTML</code> page.</p>
<p>Let’s update the navigation links to point to the new markdown pages as shown below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 NavigationBar.astro --&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/"</span>&gt;</span>Home<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/philosophies"</span>&gt;</span>Philosophies<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/beyond-tech"</span>&gt;</span>Beyond technology<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
</code></pre>
<p>Clicking any of these links should now lead us to their appropriate pages.</p>
<h2 id="heading-markdown-layouts">Markdown Layouts</h2>
<p>Let’s face it – we won’t be winning any design awards for our current markdown pages. This is because they seem off and don’t share the same layout as our existing page. Can we fix this?</p>
<p>You’ve probably realised I ask questions and then provide answers. All right, you’ve got me. So that’s my trick to make you think about a problem — hoverer brief — before explaining the solution.</p>
<p>Believe it or not, Astro component frontmatter was inspired by markdown. The original markdown syntax supports frontmatter for providing metadata about the document. For example, we could add a <code>title</code> metadata as shown below:</p>
<pre><code class="lang-ts">---
title: Understanding Astro
---
</code></pre>
<p>This is excellent news because Astro leverages this to provide layouts for markdown pages.</p>
<p>Instead of the <em>so dull I can’t take it</em> page, we can utilise a layout to bring some reusable structure to all our markdown pages.</p>
<p>Let’s get started.</p>
<p>With Astro markdown pages, we can provide layouts for a markdown page by providing a layout frontmatter metadata as shown below:</p>
<pre><code class="lang-ts">---
layout: path-to-layout
---
</code></pre>
<p>First, let’s reuse the same <code>Main</code> layout by adding the following to both markdown pages:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// add at the top of the Markdown pages.</span>
---
layout: ../layouts/Main.astro
---
</code></pre>
<p>The markdown pages should now reuse our existing layout with the theming, navigation and footer all set in place.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-03-at-04.40.15.png" alt="Using the Main layout in the markdown pages. " width="990" height="704" loading="lazy">
<em>Using the Main layout in the markdown pages.</em></p>
<p>Since <code>Main.astro</code> includes our <code>global.css</code> files, let’s go ahead and provide some default global styles for paragraphs and lists:</p>
<pre><code class="lang-css">{<span class="hljs-comment">/** 📂 src/styles/global.css **/</span>}
<span class="hljs-selector-tag">p</span>,
<span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1rem</span>;
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--gray-<span class="hljs-number">400</span>);
  <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0.8</span>;
}

<span class="hljs-selector-tag">li</span> {
  <span class="hljs-attribute">margin</span>: <span class="hljs-number">1rem</span> <span class="hljs-number">0</span>;
}
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-11-at-07.51.10@2x.png" alt="Global list styles are now applied to the Markdown pages." width="1808" height="1362" loading="lazy">
<em>Global list styles are now applied to the Markdown pages.</em></p>
<p>We should now have these styles take effect on our markdown pages! Isn’t life better with shared layout components? 😉</p>
<h2 id="heading-how-to-compose-layouts">How to Compose Layouts</h2>
<p>Layouts are Astro components, meaning we can compose them – that is, render one layout in another.</p>
<p>For example, let’s create a separate <code>Blog.astro</code> layout that composes our base <code>Main.astro</code> layout.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Blog.astro</span>
---
<span class="hljs-keyword">import</span> Main <span class="hljs-keyword">from</span> <span class="hljs-string">"./Main.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Main</span>&gt;</span></span>
</code></pre>
<p>Composing the layouts in this way means we can reuse all the good stuff in <code>Main.astro</code> while extending <code>Blog.astro</code> to include only blog-specific elements.</p>
<p>The separation of concern significantly improves legibility and forces each layout to have a single responsibility.</p>
<p>Now, at this point, the markdown pages have the same layout markup and styles from <code>Main.astro</code>. We’ve made no customisations. But we can already change the <code>beyond-tech</code> and <code>philosophies</code> pages to use the new <code>Blog.astro</code> layout as shown below:</p>
<pre><code class="lang-md">---
<span class="hljs-section">layout: ../layouts/Blog.astro
---</span>
</code></pre>
<h2 id="heading-component-props">Component Props</h2>
<p>As we build reusable components, we often find situations where we must customise certain values within a component. For example, consider the <code>&lt;title&gt;</code> in our <code>Main.astro</code> layout component:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Main.astro</span>
&lt;title&gt;Astro&lt;/title&gt;
</code></pre>
<p>A hardcoded <code>title</code> on every page where the <code>Main</code> layout is used is ridiculous.</p>
<p>To foster reusability, components can accept properties. These are commonly known as <strong>props</strong>.</p>
<p>Props are passed to components as attributes.</p>
<pre><code class="lang-js">&lt;Main title=<span class="hljs-string">"Some title"</span> /&gt;
</code></pre>
<p>The prop values are then accessed via <code>Astro.props</code>. This is better explained with an example.</p>
<p>Go ahead and update <code>Main</code> to accept a <code>title</code> prop as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Main.astro </span>
--- 
<span class="hljs-comment">// ...</span>
<span class="hljs-keyword">const</span> { title } = Astro.props;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    {/** ... **/}
    {/** 👀 look here **/}
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
     {/** ... **/}
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>To enforce TypeScript checks, define the <code>Props</code> type alias or interface.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Either of these is valid </span>
type Props = {
  <span class="hljs-attr">title</span>: string 
}

interface Props {
  <span class="hljs-attr">title</span>: string 
}
</code></pre>
<p>For simplicity, I’ll stick to a type alias for the <code>Main</code> layout:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Main.astro</span>
---
type Props = {
  <span class="hljs-attr">title</span>: string 
}

<span class="hljs-keyword">const</span> { title } = Astro.props;
---
<span class="hljs-comment">// ...</span>
</code></pre>
<p>With the type declared, we’ll have TypeScript error(s) in files where we’ve used <code>&lt;Main&gt;</code> without the required <code>title</code> prop.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-03-at-06.01.52.png" alt="Invalid title props error. " width="490" height="276" loading="lazy">
<em>Invalid title props error.</em></p>
<p>Update the <code>index.astro</code> and <code>Blog.astro</code> pages to pass a <code>title</code> prop to <code>Main</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/index.astro</span>
&lt;Main title=<span class="hljs-string">"Frau Katarina"</span>&gt; 
{<span class="hljs-comment">/* ... */</span>}
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/Blog.astro</span>
&lt;Main title=<span class="hljs-string">"Frau Katarina | Blog"</span>&gt;
{<span class="hljs-comment">/* ... */</span>}
</code></pre>
<h2 id="heading-how-to-leverage-markdown-frontmatter-properties">How to Leverage Markdown Frontmatter Properties</h2>
<p>All markdown pages in our application will have a title, subtitle, and poster. Luckily, a great way to represent these is via frontmatter properties.</p>
<p>Update the markdown pages to now include these properties, as shown below.</p>
<p><code>📂 src/pages/beyond-tech.md</code>:</p>
<pre><code class="lang-md">---
layout: ../layouts/Blog.astro
poster: "/images/road-trip.jpg"
title: "Beyond Technology"
<span class="hljs-section">subtitle: "Humans are multi-faceted. Beyond tech, I indulge in the following:"
---</span>
...
</code></pre>
<p><code>📂 src/pages/philosophies.md</code>:</p>
<pre><code class="lang-md">---
layout: ../layouts/Blog.astro
poster: "/images/philosophies.jpg"
title: "My Guiding Philosophies"
<span class="hljs-section">subtitle: "These are the philosophies that guide every decision and action I make."
---</span>
...
</code></pre>
<p>Note that <code>poster</code> points to image paths. These paths reference the <code>public</code> directory. So <code>/images/philosophies.jpg</code> points to an image in <code>public/images/philosophies.jpg</code>.</p>
<p>If you’re coding along, feel free to download any image from Unsplash and move them to the <code>public</code> directory.</p>
<p>Adding metadata to our markdown pages doesn’t do us any good if we can't use them.</p>
<p>Luckily, markdown layouts have a unique superpower — they can access markdown frontmatter via <code>Astro.props.frontmatter</code>.</p>
<p>Let’s go ahead and globally handle this in our <code>Blog.astro</code> layout component. Below’s the component script section:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// 📂 src/layouts/Blog.astro </span>
---
<span class="hljs-comment">// import the type utility for the markdown layout props</span>
<span class="hljs-keyword">import</span> <span class="hljs-keyword">type</span> { MarkdownLayoutProps } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;
<span class="hljs-comment">// import the base layout: Main.astro</span>
<span class="hljs-keyword">import</span> Main <span class="hljs-keyword">from</span> <span class="hljs-string">"./Main.astro"</span>;

<span class="hljs-comment">// defined the Props type </span>
<span class="hljs-keyword">type</span> Props = MarkdownLayoutProps&lt;{
  <span class="hljs-comment">// Define the expected frontmatter props here</span>
  title: <span class="hljs-built_in">string</span>;
  poster: <span class="hljs-built_in">string</span>;
  subtitle: <span class="hljs-built_in">string</span>;
}&gt;;

<span class="hljs-comment">// get properties from the markdown frontmatter</span>
<span class="hljs-keyword">const</span> { poster, title, subtitle } = Astro.props.frontmatter;
---
</code></pre>
<ul>
<li>The <code>MarkdownLayoutProps</code> utility type accepts a generic and returns the type for all the properties available to a markdown layout. So feel free to inspect the entire shape.</li>
<li><code>MarkdownLayoutProps</code> accepts our frontmatter property type definition as a generic, that is <code>title</code>, <code>poster</code> and <code>subtitle</code>. These are properties we’ve added in the frontmatter of our Markdown pages.</li>
<li><code>type Props = ...</code> or <code>interface Props {}</code> is how we provide types for an Astro component.</li>
<li>The final line deconstructs the properties from <code>Astro.props.frontmatter</code> with full TypeScript support.</li>
</ul>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-03-at-05.16.20.png" alt="Typescript support in the Markdown layout." width="579" height="160" loading="lazy">
<em>Typescript support in the Markdown layout.</em></p>
<p>Equally update the layout markup to render the image, title, and subtitle:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/layouts/Blog.astro --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">Main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">figure</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"figure"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
      <span class="hljs-attr">src</span>=<span class="hljs-string">{poster}</span>
      <span class="hljs-attr">alt</span>=<span class="hljs-string">""</span>
      <span class="hljs-attr">width</span>=<span class="hljs-string">"100%"</span>
      <span class="hljs-attr">height</span>=<span class="hljs-string">"480px"</span>
      <span class="hljs-attr">class</span>=<span class="hljs-string">"figure__image"</span>
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">figcaption</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"figure__caption"</span>&gt;</span>
      Poster image for {title.toLowerCase()}
    <span class="hljs-tag">&lt;/<span class="hljs-name">figcaption</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">figure</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{subtitle}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Main</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">h1</span> + <span class="hljs-selector-tag">h2</span> {
    <span class="hljs-attribute">margin-bottom</span>: <span class="hljs-number">3rem</span>;
  }

  <span class="hljs-selector-class">.figure</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
  }

  <span class="hljs-selector-class">.figure__image</span> {
    <span class="hljs-attribute">max-width</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
  }

  <span class="hljs-selector-class">.figure__caption</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">0.9rem</span>;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Most of the markup is arguably standard. However, note the <code>title.toLowerCase()</code> call for the poster image caption. This is possible because any valid JavaScript expression can be evaluated within curly braces <code>{ }</code> in the component markup.</p>
<p>Our markdown pages will now have styled titles, subtitles, and poster images. With all this handled in one place — the markdown layout.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-03-at-05.19.26.png" alt="The fully formed Markdown page." width="708" height="921" loading="lazy">
<em>The fully formed Markdown page.</em></p>
<h2 id="heading-interactive-navigation-state">Interactive Navigation State</h2>
<p>Now that we’re pros at handling interactive scripts in Astro let’s go ahead and make sure that we style our active navigation links differently.</p>
<p>As with all things programming, there are different ways to achieve this, but we will go ahead and script this.</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/components/NavigationBar.astro --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">const</span> { pathname } = <span class="hljs-built_in">window</span>.location;
  <span class="hljs-keyword">const</span> activeNavigationElement = <span class="hljs-built_in">document</span>.querySelector(
    <span class="hljs-string">`nav a[href="<span class="hljs-subst">${pathname}</span>"]`</span>
  );

  <span class="hljs-keyword">if</span> (activeNavigationElement) {
    activeNavigationElement.classList.add(<span class="hljs-string">"active"</span>);
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<ul>
<li>Get the <code>pathname</code> from the <code>location</code> object. This will be in the form <code>"/beyond-tech"</code>, <code>"/philosophies</code> or <code>"/"</code>.</li>
<li>Since the <code>pathname</code> corresponds to the <code>href</code> on the anchor tag element, we may select the active anchor tag via: <code>document.querySelector(</code>nav a[href="${pathname}"]<code>).</code></li>
<li>Finally, we add the <code>active</code> class to the active anchor tag.</li>
</ul>
<p>Finally, add the relevant style for the active tag:</p>
<pre><code class="lang-css"><span class="hljs-comment">/* 📂 src/components/NavigationBar.astro */</span>
&lt;<span class="hljs-selector-tag">style</span>&gt;
  <span class="hljs-comment">/* ... */</span>
 <span class="hljs-selector-tag">a</span><span class="hljs-selector-class">.active</span> {
  <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--grey-<span class="hljs-number">900</span>);
  <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--background);
 }
&lt;/<span class="hljs-selector-tag">style</span>&gt;
</code></pre>
<p>Violà! We should now have the active anchor tag styled differently.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-03-at-09.44.02.png" alt="Active anchor tag styles." width="855" height="230" loading="lazy">
<em>Active anchor tag styles.</em></p>
<h2 id="heading-component-composition">Component Composition</h2>
<p>Our first look at component composition was with the <code>Main</code> and <code>Blog</code> layouts. Let’s take this further.</p>
<p>Our goal is to create a set of different yet identical cards. Each card acts as a link to a blog and will have a title and some background gradient.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-04-at-09.44.58.png" alt="The eventual card layout we will build." width="778" height="293" loading="lazy">
<em>The eventual card layout we will build.</em></p>
<p>To achieve this, we’ll have a <code>Cards.astro</code> component that renders multiple <code>Card.astro</code> components.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/b.png" alt="The card composition visualised. " width="2000" height="808" loading="lazy">
<em>The card composition visualised.</em></p>
<p>Let’s start by creating <code>Card.astro</code>.</p>
<p>Define the relevant component props and relevant markup as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/Card.astro</span>
---
{<span class="hljs-comment">/** Export the Props type alias **/</span>}
<span class="hljs-keyword">export</span> type Props = {
  <span class="hljs-attr">to</span>: string;
  title: string;
  gradientFrom: string;
  gradientTo: string;
};

<span class="hljs-comment">// Get component props from Astro.props</span>
<span class="hljs-keyword">const</span> { title, to } = Astro.props;
---
</code></pre>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{to}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card__inner"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card__title"</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Render the arrow via HTML entity name: → = &amp;rarr;--&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card__footer"</span>&gt;</span><span class="hljs-symbol">&amp;rarr;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-class">.card</span> {
   <span class="hljs-comment">/** local CSS variable reused below */</span>
    <span class="hljs-attribute">--radius</span>: <span class="hljs-number">10px</span>;

    <span class="hljs-attribute">padding</span>: <span class="hljs-number">4px</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-built_in">var</span>(--radius);
    <span class="hljs-attribute">text-decoration</span>: none;
    <span class="hljs-attribute">transition</span>: all <span class="hljs-number">0.2s</span> ease-in-out;
  }

  <span class="hljs-selector-class">.card</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">transform</span>: <span class="hljs-built_in">scale</span>(<span class="hljs-number">0.95</span>);
  }

  <span class="hljs-selector-class">.card__inner</span> {
    <span class="hljs-attribute">background</span>: <span class="hljs-built_in">var</span>(--background);
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">1.5rem</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-built_in">var</span>(--radius);
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-direction</span>: column;
  }

  <span class="hljs-selector-class">.card__title</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2rem</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--grey-<span class="hljs-number">900</span>);
    <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">500</span>;
    <span class="hljs-attribute">line-height</span>: <span class="hljs-number">1.75rem</span>;
  }

  <span class="hljs-selector-class">.card__footer</span> {
    <span class="hljs-attribute">padding-top</span>: <span class="hljs-number">2rem</span>;
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1.2rem</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--grey-<span class="hljs-number">900</span>);
    <span class="hljs-attribute">margin</span>: auto <span class="hljs-number">0</span> <span class="hljs-number">0</span> auto;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>Now, go ahead and create the <code>Cards.astro</code> component as follows:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/Cards.astro</span>
---
<span class="hljs-comment">// Import the Card component</span>
<span class="hljs-keyword">import</span> Card <span class="hljs-keyword">from</span> <span class="hljs-string">"./Card.astro"</span>;
<span class="hljs-comment">// Import the Card Props type</span>
<span class="hljs-keyword">import</span> type { Props <span class="hljs-keyword">as</span> CardProp } <span class="hljs-keyword">from</span> <span class="hljs-string">"./Card.astro"</span>;

<span class="hljs-comment">// Define the Props for this component</span>
type Props = {
  <span class="hljs-attr">cards</span>: CardProp[]; <span class="hljs-comment">// accepts an array of CardProps</span>
};

<span class="hljs-comment">// Retrieve the cards prop</span>
<span class="hljs-keyword">const</span> { cards } = Astro.props;
---
</code></pre>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"cards"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- Dynamically render multiple Card components and spread the required card props --&gt;</span>
   {cards.map((card) =&gt; <span class="hljs-tag">&lt;<span class="hljs-name">Card</span> {<span class="hljs-attr">...card</span>} /&gt;</span>)}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-class">.cards</span> {
    <span class="hljs-attribute">display</span>: flex;
    <span class="hljs-attribute">flex-direction</span>: column;
    <span class="hljs-attribute">gap</span>: <span class="hljs-number">1rem</span>;
  }

  <span class="hljs-comment">/* Since this is standard CSS, we can have media queries here */</span>
  <span class="hljs-keyword">@media</span> screen <span class="hljs-keyword">and</span> (<span class="hljs-attribute">min-width:</span> <span class="hljs-number">768px</span>) {
    <span class="hljs-selector-class">.cards</span> {
      <span class="hljs-attribute">flex-direction</span>: row;
    }
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>To see the fruits of our labour, we must now import and render <code>Cards</code> in the <code>index.astro</code> page component.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro </span>
---
<span class="hljs-comment">// ...</span>
<span class="hljs-keyword">import</span> Cards <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Cards.astro"</span>;
---
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"profile"</span>&gt;</span>
   {/** ... **/}
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  {/** 👀 look here **/}
  <span class="hljs-tag">&lt;<span class="hljs-name">Cards</span>
    <span class="hljs-attr">cards</span>=<span class="hljs-string">{[</span>
      {
        <span class="hljs-attr">title:</span> "<span class="hljs-attr">Here</span> <span class="hljs-attr">are</span> <span class="hljs-attr">my</span> <span class="hljs-attr">guiding</span> <span class="hljs-attr">philosophies</span> <span class="hljs-attr">for</span> <span class="hljs-attr">life</span>",
        <span class="hljs-attr">gradientFrom:</span> "#<span class="hljs-attr">818cf8</span>",
        <span class="hljs-attr">gradientTo:</span> "#<span class="hljs-attr">d8b4fe</span>",
        <span class="hljs-attr">to:</span> "/<span class="hljs-attr">philosophies</span>",
      },
      {
        <span class="hljs-attr">title:</span> "<span class="hljs-attr">A</span> <span class="hljs-attr">summary</span> <span class="hljs-attr">of</span> <span class="hljs-attr">my</span> <span class="hljs-attr">work</span> <span class="hljs-attr">history</span>",
        <span class="hljs-attr">gradientFrom:</span> "#<span class="hljs-attr">fde68a</span>",
        <span class="hljs-attr">gradientTo:</span> "#<span class="hljs-attr">fca5a5</span>",
        <span class="hljs-attr">to:</span> "/<span class="hljs-attr">work-summary</span>",
      },
      {
        <span class="hljs-attr">title:</span> "<span class="hljs-attr">What</span> <span class="hljs-attr">I</span> <span class="hljs-attr">do</span> <span class="hljs-attr">beyond</span> <span class="hljs-attr">technology</span>",
        <span class="hljs-attr">gradientFrom:</span> "#<span class="hljs-attr">6ee7b7</span>",
        <span class="hljs-attr">gradientTo:</span> "#<span class="hljs-attr">9333ea</span>",
        <span class="hljs-attr">to:</span> "/<span class="hljs-attr">beyond-tech</span>",
      },
    ]}
  /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Main</span>&gt;</span></span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-04-at-10.18.23.png" alt="The rendered cards." width="931" height="581" loading="lazy">
<em>The rendered cards.</em></p>
<p>Clicking any of the links will point to the respective blog page.</p>
<p>Let’s not forget to add the new <code>work-summary.md</code> page:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/work-summary.md</span>
---
layout: ../layouts/Blog.astro
<span class="hljs-attr">poster</span>: <span class="hljs-string">"/images/work-summary.jpg"</span>
<span class="hljs-attr">title</span>: <span class="hljs-string">"Work summary"</span>
<span class="hljs-attr">subtitle</span>: <span class="hljs-string">"A summary of my work:"</span>
---

- VP Engineering at Google
- VP Engineering at Facebook
- VP Engineering at Tesla
- VP Engineering at Amazon
- VP Engineering at Netflix
</code></pre>
<p>There we go!</p>
<h2 id="heading-the-template-flow-of-data">The Template Flow of Data</h2>
<p>As we’ve discussed, the data in the frontmatter runs on the server and is not available in the browser.</p>
<p>As we’ve built our application, we’ve frequently leveraged data in the frontmatter in the template section, as shown below:</p>
<pre><code class="lang-js">---
 <span class="hljs-keyword">const</span> data = <span class="hljs-string">"Understanding Astro"</span>
---

<span class="hljs-comment">//Use data in the template </span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{data}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p>This is easy to reason about for our static website. We know this will eventually be compiled into HTML.</p>
<p>But consider a more robust markup that includes <code>&lt;style&gt;</code> and <code>&lt;script&gt;</code> elements. How do we reference data from the frontmatter in these markup sections?</p>
<pre><code class="lang-js">---
 <span class="hljs-keyword">const</span> data = <span class="hljs-string">"Understanding Astro"</span>
---

<span class="hljs-comment">// ✅ Use data in the template </span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{data}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>

<span class="hljs-comment">// styles </span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
 {<span class="hljs-comment">/** ❌referencing data here will fail */</span>}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span> 

<span class="hljs-comment">// scripts </span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
{<span class="hljs-comment">/** ❌referencing data here will fail */</span>}
 <span class="hljs-built_in">console</span>.log(data)
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>One answer is via the <code>define:vars</code> template directive.</p>
<p><code>define:vars</code> will pass our variables from the frontmatter into the client <code>&lt;script&gt;</code> or <code>&lt;style&gt;</code>. It’s important to note that only JSON serialisable values work here.</p>
<p>Let’s give this a shot.</p>
<p>We must reference the <code>gradientFrom</code> and <code>gradientTo</code> variables passed as props in our <code>&lt;style&gt;</code>.</p>
<p>First, to make the variables available within <code>&lt;style&gt;</code>, we’ll go ahead and use <code>define:vars</code> as follows:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/Card.astro</span>
---
<span class="hljs-keyword">const</span> { title, to, gradientFrom, gradientTo } = Astro.props;
<span class="hljs-comment">// ... </span>
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span> <span class="hljs-attr">define:vars</span>=<span class="hljs-string">{{gradientFrom,</span> <span class="hljs-attr">gradientTo</span> }}&gt;</span><span class="css">
  {<span class="hljs-comment">/** ... **/</span>}
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre>
<p><code>define:vars</code> accepts an object of variables we want available within <code>&lt;style&gt;</code>.</p>
<p>The variables are defined but not used yet.</p>
<p>Now, we can reference the variables via custom properties (aka css variables) as shown below:</p>
<pre><code class="lang-css"><span class="hljs-comment">/** 📂 src/components/Card.astro **/</span>
&lt;<span class="hljs-selector-tag">style</span> <span class="hljs-selector-tag">define</span><span class="hljs-selector-pseudo">:vars</span>={{gradientFrom, gradientTo }}&gt;
  <span class="hljs-comment">/** 👀 look here **/</span>
  <span class="hljs-selector-class">.card</span> {
    <span class="hljs-attribute">background-image</span>: <span class="hljs-built_in">linear-gradient</span>(
      to right,
      var(--gradientFrom), 
      <span class="hljs-built_in">var</span>(--gradientTo)
    );
  }
 <span class="hljs-comment">/** ... **/</span>
&lt;/<span class="hljs-selector-tag">style</span>&gt;
</code></pre>
<p>And voilà!</p>
<p>Our cards are now more beautiful than ever.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-04-at-10.45.36.png" alt="Applying dynamic gradients to the cards. " width="830" height="443" loading="lazy">
<em>Applying dynamic gradients to the cards.</em></p>
<h2 id="heading-the-dark-side-of-definevars">The Dark Side of <code>define:vars</code></h2>
<p>We’ve seen <code>define:vars</code> come in handy for using variables from the frontmatter of an Astro component. But be careful when using <code>define:vars</code> with scripts.</p>
<p>Using <code>define:vars</code> with a <code>&lt;script&gt;</code> is similar to using the <code>is:inline</code> directive.</p>
<p>Astro will not bundle the script and will be added multiple times if the same component is rendered more than once on a page.</p>
<p>Here’s an example to make this clear.</p>
<p>In <code>Card.astro</code>, go ahead and add a <code>&lt;script&gt;</code> with the <code>define:vars</code> directive as follows:</p>
<pre><code class="lang-js"><span class="hljs-comment">/** 📂 src/components/Card.astro **/</span>
&lt;script define:vars={{ gradientFrom }}&gt;
  <span class="hljs-built_in">console</span>.log(gradientFrom);
&lt;/script&gt;
</code></pre>
<p>Inspect the elements via the developer tools. You’ll notice that the <code>&lt;script&gt;</code> is inlined and unprocessed, that is, just as we’ve written it, apart from being wrapped in an immediately invoked function execution (IIFE).</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-04-at-12.07.32.png" alt="The inlined scripts. " width="1012" height="562" loading="lazy">
<em>The inlined scripts.</em></p>
<p>The script is also added three times — with a different value of <code>gradientFrom</code> for each rendered card.</p>
<p>With scripts, a better solution (except the inline behaviour is ideal for your use case) is to pass the data from the component frontmatter to the rendered element via <code>data-</code> attributes and then access these via JavaScript.</p>
<p>For example, we may rewrite the previous solution as shown below:</p>
<pre><code class="lang-html">---

---
<span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{to}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"card"</span> <span class="hljs-attr">data-gradientfrom</span>=<span class="hljs-string">{gradientFrom}</span>&gt;</span>
 ...
<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
...
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">const</span> card = <span class="hljs-built_in">document</span>.querySelector(<span class="hljs-string">".card"</span>);

  <span class="hljs-comment">// narrow the type of card to HTMLElement to access ".dataset" </span>
  <span class="hljs-keyword">if</span> (card <span class="hljs-keyword">instanceof</span> HTMLElement) {
    <span class="hljs-comment">// access data in dataset.gradientfrom</span>
    <span class="hljs-built_in">console</span>.log(card.dataset.gradientfrom);
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>Note that this is a contrived example and only retrieves the first card element with its associated <code>gradientfrom</code> data. Still, this demonstrates how to prevent unwanted behaviours with <code>define:vars</code> in <code>&lt;script&gt;</code>s.</p>
<h2 id="heading-how-to-load-multiple-local-files">How to Load Multiple Local Files</h2>
<p>Let’s go ahead and create a new <code>blog</code> directory to hold some more markdown pages. The pages and their content are shown below:</p>
<p><code>📂 pages/blogs/rust-javascript-tooling.md</code> :</p>
<pre><code class="lang-md">---
layout: "../../layouts/Blog.astro"
poster: "/images/adventure.jpg"
title: "Why Rust is the Future of Javascript Tooling"
<span class="hljs-section">subtitle: "How to create fast, speedy developer experiences."
---</span>

<span class="hljs-bullet">-</span> Rust is fast
<span class="hljs-bullet">-</span> Yes, it is fast
<span class="hljs-bullet">-</span> Touted as the new C++
<span class="hljs-bullet">-</span> Did I mention it's pretty fast?
</code></pre>
<p><code>📂 pages/blogs/sleep-more.md</code> :</p>
<pre><code class="lang-md">---
layout: "../../layouts/Blog.astro"
poster: "/images/sleeping-cat.jpg"
title: "Why you should sleep more"
<span class="hljs-section">subtitle: "Sleep is great for you. Here's why:"
---</span>

<span class="hljs-bullet">-</span> Sleep
<span class="hljs-bullet">-</span> Sleep more
<span class="hljs-bullet">-</span> Sleep a little more
</code></pre>
<p><code>📂 pages/blogs/typescript-new-javascript.md</code>  :</p>
<pre><code class="lang-md">---
layout: "../../layouts/Blog.astro"
poster: "/images/coding.jpg"
title: "Typescript is the new Javascript"
<span class="hljs-section">subtitle: "Typescript is becoming a standard for web development these days:"
---</span>

<span class="hljs-bullet">-</span> Type safety
<span class="hljs-bullet">-</span> Type safety!
<span class="hljs-bullet">-</span> Even more type safety!
</code></pre>
<p>We aim to list these blog titles on our home page. One way to do this would be to render all link elements in <code>index.astro</code> manually:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/pages/index.astro --&gt;</span> 
...
<span class="hljs-tag">&lt;<span class="hljs-name">Main</span>&gt;</span>
 ... 
 <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"featured-blogs"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h3</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"featured-blogs__title"</span>&gt;</span>Featured Blogs<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"featured-blogs__description"</span>&gt;</span>
      Opinion pieces that will change everything you know about web development.
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

 <span class="hljs-tag">&lt;<span class="hljs-name">ol</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"blogs"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"blogs__list"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"blogs/typescript-new-javascript"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"blog__link"</span>
        &gt;</span>Typescript is the new Javascript<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>
      &gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"blogs__list"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/blogs/rust-javascript-tooling"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"blog__link"</span>
        &gt;</span>Why Rust is the future of Javascript tooling<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>
      &gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"blogs__list"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/blogs/sleep-more"</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"blog__link"</span>
        &gt;</span>Why you should sleep more<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>
      &gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">ol</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Main</span>&gt;</span>
</code></pre>
<p>Then update our component styles:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/pages/index.astro --&gt;</span> 
...
<span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  ... 
  <span class="hljs-selector-class">.featured-blogs</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">3rem</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span> <span class="hljs-number">0</span>;
  }
  <span class="hljs-selector-class">.featured-blogs__title</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">2rem</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--gray-<span class="hljs-number">900</span>);
  }

  <span class="hljs-selector-class">.featured-blogs__description</span> {
    <span class="hljs-attribute">margin-top</span>: -<span class="hljs-number">1.2rem</span>;
  }

  <span class="hljs-selector-class">.blogs</span> {
    <span class="hljs-attribute">font-size</span>: <span class="hljs-number">1rem</span>;
    <span class="hljs-attribute">font-weight</span>: <span class="hljs-number">500</span>;
  }

  <span class="hljs-selector-class">.blogs__list</span> {
    <span class="hljs-attribute">border-bottom</span>: <span class="hljs-number">1px</span> solid;
    <span class="hljs-attribute">border-color</span>: <span class="hljs-built_in">var</span>(--gray-<span class="hljs-number">200</span>);
  }

  <span class="hljs-selector-class">.blog__link</span> {
    <span class="hljs-attribute">opacity</span>: <span class="hljs-number">1</span>;
    <span class="hljs-attribute">height</span>: <span class="hljs-number">100%</span>;
    <span class="hljs-attribute">display</span>: block;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">1rem</span> <span class="hljs-number">0</span>;
    <span class="hljs-attribute">color</span>: <span class="hljs-built_in">var</span>(--gray-<span class="hljs-number">200</span>);
    <span class="hljs-attribute">text-decoration</span>: none;
    <span class="hljs-attribute">transition</span>: opacity <span class="hljs-number">0.2s</span> ease-in-out;
  }

  <span class="hljs-selector-class">.blog__link</span><span class="hljs-selector-pseudo">:hover</span> {
    <span class="hljs-attribute">opacity</span>: <span class="hljs-number">0.7</span>;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
</code></pre>
<p>This isn’t necessarily a wrong approach to getting this done. We will now have a list of the blogs, as expected.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-11-at-12.52.18@2x.png" alt="The rendered blog list." width="2002" height="991" loading="lazy">
<em>The rendered blog list.</em></p>
<p>A better solution is to use <code>Astro.glob()</code> to load multiple files.</p>
<p><code>Astro.glob()</code> accepts a single <code>URL</code> glob parameter of the files we’d like to import. <code>glob()</code> will then return an array of the exports from the matching file.</p>
<p>Talk is cheap, so let’s put this into action.</p>
<p>Instead of manually writing out the list of blog articles, we will use <code>Astro.glob()</code> to fetch all the blog posts:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro </span>
---
<span class="hljs-keyword">const</span> blogs = <span class="hljs-keyword">await</span> Astro.glob&lt;{
  <span class="hljs-attr">poster</span>: string;
  title: string;
  subtitle: string;
}&gt;(<span class="hljs-string">"../pages/blogs/*.md"</span>);
...
---
...
</code></pre>
<ul>
<li>Note the argument passed to <code>.glob</code>, that is <code>../pages/blogs/*.md</code>. This relative glob path represents all markdown files in the <code>/blogs</code> directory.</li>
<li>Also note the typing provided. <code>.glob</code> implements a generic, which, in this case, represents the markdown frontmatter object type. </li>
</ul>
<pre><code class="lang-js">{          
    <span class="hljs-attr">poster</span>: string;
    title: string;
    subtitle: string;    
}
</code></pre>
<p>Now, we may replace the manual list with a dynamically rendered list, as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro </span>
...
  &lt;ol&gt;
    {
      blogs.map(<span class="hljs-function">(<span class="hljs-params">blog</span>) =&gt;</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">li</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"blogs__list"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{blog.url}</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"blog__link"</span>&gt;</span>
            {blog.frontmatter.title}
          <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span></span>
      ))
    }
  &lt;/ol&gt;
</code></pre>
<ul>
<li>Dynamically render the blog list using the <code>.map</code> array function.</li>
<li><code>Astro.glob()</code> returns markdown properties including frontmatter and <code>url</code> where <code>blog.url</code> refers to the browser url path for the markdown file.</li>
</ul>
<p>And voilà! Same result with a much neater implementation.</p>
<h2 id="heading-how-to-deploy-a-static-astro-site">How to Deploy a Static Astro Site</h2>
<p>We’ve come a long way! Now, let’s deploy this baby into the wild.</p>
<p>Deploying a static website is relatively the same regardless of the technology used to create the site.</p>
<p>At the end of your deployment build, we’ll have static assets to deploy to any service we choose.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/generate-prod-build-1.png" alt="Image" width="600" height="400" loading="lazy">
<em>Generating production builds.</em></p>
<p>Once this is done, we must wire up a static web server to serve this content when your users visit the deployed site.</p>
<p>NB: a static web server is a web server that serves static content. It essentially serves any files (for example, HTML, CSS, JS) the client requests.</p>
<p>This breaks down the process of deploying a static website into two parts:</p>
<ol>
<li>Create the static production assets</li>
<li>Serve the static assets via a static web server</li>
</ol>
<p>Let’s go through these steps.</p>
<h3 id="heading-1-create-static-production-assets">1. Create static production assets</h3>
<p>To build our application for production, run the command:</p>
<pre><code class="lang-bash">npm run build
</code></pre>
<p>This will internally run the <code>astro build</code> command and build our application production static assets.</p>
<p>By default, these assets will exist in the <code>dist</code> folder.</p>
<h3 id="heading-2-serve-the-static-assets-via-a-static-web-server">2. Serve the static assets via a static web server</h3>
<p>Choosing a web server will come down to your choice. I’ll go ahead and explain how to use Netlify. But the steps you'll take with your web server provider will look similar.</p>
<p>Go over to Netlify and create an account.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-01-25-at-04.51.46@2x.png" alt="The Netlify homepage." width="2000" height="1250" loading="lazy">
<em>The Netlify homepage.</em></p>
<p>Once you create an account and sign in, you’ll find a manual section to deploy a site.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-01-25-at-04.56.37@2x.png" alt="The Netlify dashboard. " width="2000" height="1250" loading="lazy">
<em>The Netlify dashboard.</em></p>
<p>Now, click <code>browse to upload</code> and upload the <code>dist</code> folder containing our static production assets.</p>
<p>Once the upload is completed, you’ll have your site deployed with a random public URL, as shown below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-01-25-at-04.57.57@2x.png" alt="Deployed Netlify site URL." width="2000" height="1250" loading="lazy">
<em>Deployed Netlify site URL.</em></p>
<p>Visit the URL to view your newly deployed website!</p>
<h2 id="heading-the-problem-with-manual-deployments">The Problem with Manual Deployments</h2>
<p>Manual deployments are great for conceptually breaking down the process of deploying a static website.</p>
<p>But in the real world, you may find this less optimal.</p>
<p>The main challenge here is that every change made to your website requires you to build the application and re-upload it to your server manually.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/manual-redeployment.png" alt="Image" width="600" height="400" loading="lazy">
<em>Manually redeploying after new changes.</em></p>
<p>This is a well-known problem with a standardised solution. The solution involves automating the entire process of deploying static websites by connecting your website to a Git provider.</p>
<h2 id="heading-how-to-automate-the-deployment-of-a-static-website">How to Automate the Deployment of a Static Website</h2>
<p>Automating the deployment of a static website looks something like this:</p>
<p><strong>Step 1</strong>: Write and push your code to a Git provider like GitHub.</p>
<p><strong>Step 2</strong>: Connect the GitHub project to your static web server provider, for example Netlify.</p>
<p><strong>Step 3</strong>: You provide your website’s <code>build</code> command and the location of the built assets to your web server provider, for example Netlify.</p>
<p><strong>Step 4</strong>: Your web server provider automatically runs the build command and serves your static assets.</p>
<p><strong>Step 5</strong>: Anytime you make changes to the GitHub project, your web server provider picks up the changes and reruns step 4, that is automatically deploying your website changes.</p>
<p>To see this process in practice with Netlify, go over <a target="_blank" href="https://app.netlify.com/start">to your dashboard</a> and connect a Git provider (step 1).</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-01-25-at-05.46.08@2x.png" alt="Netlify: connecting a Git provider." width="2000" height="1250" loading="lazy">
<em>Netlify: connecting a Git provider.</em></p>
<p>I’ll go ahead to select GitHub, authorise Netlify, and select the GitHub project (step 2).</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-01-25-at-05.47.23@2x.png" alt="Netlify: selecting the Github project." width="2000" height="1250" loading="lazy">
<em>Netlify: selecting the Github project.</em></p>
<p>Once that’s selected, provide the settings for your application deployment (Step 3). By default, Netlify will suggest the <code>build</code> and <code>publish directory</code>. Check these to make sure there are no errors.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-01-25-at-05.49.46@2x.png" alt="Netlify: suggested build command and publish directory." width="2000" height="1250" loading="lazy">
<em>Netlify: suggested build command and publish directory.</em></p>
<p>Hit deploy, and your site will be live in seconds (step 4).</p>
<p>To see the redeployment after a new change, push a new change to the connected git repository.</p>
<h2 id="heading-how-fast-is-our-astro-website">How Fast is Our Astro Website?</h2>
<p>Astro boasts of insanely fast websites compared to frameworks like React or Vue.</p>
<p>Let’s put this to the test by following the steps below:</p>
<ul>
<li>Visit the newly deployed website on Chrome.</li>
<li>Open the Chrome developer tools.</li>
<li>Go to the Lighthouse tab.</li>
<li>Analyse the page load.</li>
</ul>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-11-at-13.42.45@2x.png" alt="Analysing page load via lighthouse." width="2000" height="1269" loading="lazy">
<em>Analysing page load via lighthouse.</em></p>
<p>Here’s my result running the test:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-11-at-13.44.24@2x.png" alt="Lighthouse 100% scores. " width="2000" height="1256" loading="lazy">
<em>Lighthouse 100% scores.</em></p>
<p>If this were a school examination, we would have just scored A+ on performance without trying.</p>
<p>This is a fast website!</p>
<p>Feel free to run the test on other pages.</p>
<h2 id="heading-wrapping-up-this-chapter">Wrapping Up This Chapter</h2>
<p>This has been a lengthy introduction to Astro! We’ve delved into building a project and learned a handful of Astro’s capabilities, from installation to project structure to the nuances of inline scripts and, eventually, project deployment.</p>
<p>Why stop here? We’ve only just scratched the surface.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-134.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chapter two.</em></p>
<h1 id="heading-chapter-2-astro-components-in-depth-1">Chapter 2: Astro Components In-Depth</h1>
<p>In this section, you'll beyond the basics and master the essential Astro entity.</p>
<h2 id="heading-what-youll-learn-1">What You’ll Learn</h2>
<ul>
<li>What zero JavaScript means in practical terms.</li>
<li>Why we should consider ditching the JavaScript runtime overhead.</li>
<li>Truly understand what an Astro component is.</li>
<li>Understand the behaviour of Astro component markup, styles and scripts.</li>
<li>Learn the powerful Astro template syntax and how it differs from <code>JSX.</code></li>
</ul>
<h2 id="heading-introduction-1">Introduction</h2>
<p>Consider the Pareto principle:</p>
<blockquote>
<p>The Pareto principle, also known as the 80/20 rule, states that 20% of the input can significantly impact 80% of the outcome in a particular situation or system.</p>
</blockquote>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/pareto.png" alt="The pareto principle illustrated" width="2000" height="1339" loading="lazy">
<em>The Pareto principle illustrated</em></p>
<p>Now, pay attention because this is where things get spicy. When it comes to working with Astro components, I've got a sneaky suspicion that that magic 20% yields a whopping 80% productivity.</p>
<p>So, let's get cracking and master these Astro components, shall we?</p>
<h2 id="heading-the-backbone-of-astro">The Backbone of Astro</h2>
<p>At the time of writing, consider the definition of Astro components from the official docs:</p>
<blockquote>
<p>Astro components are the basic building blocks of any Astro project. They are HTML-only templating components with no client-side runtime.</p>
</blockquote>
<p>The first part of the sentence is clear as daylight: <em>Astro components are the basic building blocks of any Astro project.</em></p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/building-blocks.png" alt="Like a fun game of Tetris, Astro components are how we build Astro applications." width="595" height="289" loading="lazy">
<em>Like a fun game of Tetris, Astro components are how we build Astro applications.</em></p>
<p>The second part of the sentence leaves room for interpretation or ambiguity: <em>they are HTML-only templating components with no client-side runtime.</em></p>
<p>But in this sentence lies the heartbeat of Astro components.</p>
<p>Let’s explore this in practical terms.</p>
<h3 id="heading-the-javascript-runtime-fatigue">The JavaScript runtime fatigue</h3>
<p>To truly appreciate Astro components, we must turn to our “standard” user interface framework components, for example those provided by <code>React</code> or <code>Vue</code>.</p>
<p>Your level of familiarity with these frameworks doesn’t matter. I’ll explain the following steps as clearly as possible. So trust me and follow along.</p>
<p>Firstly, create a new React project called <code>test-react-app</code> with the following terminal command:</p>
<pre><code class="lang-bash">npx create-react-app test-react-app
</code></pre>
<p>This utilises the <a target="_blank" href="https://create-react-app.dev/">create-react-app</a> utility.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-12.28.51@2x.png" alt="Creating a new React project from the terminal." width="2000" height="1548" loading="lazy">
<em>Creating a new React project from the terminal.</em></p>
<p>This will create a new React app in the <code>test-react-app</code> directory.</p>
<p>Now change the current directory, install dependencies, and start up the React application with the following command:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> test-react-app &amp;&amp; npm install &amp;&amp; npm run start
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-12.30.17@2x.png" alt="Starting the test React application." width="2000" height="1217" loading="lazy">
<em>Starting the test React application.</em></p>
<p>This will start a trivial React application on <code>http://localhost:3000/</code> or any other available local port.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-12.31.38@2x.png" alt="The React test application running in the browser." width="1944" height="1332" loading="lazy">
<em>The React test application running in the browser.</em></p>
<p>This is a contrived React application. It renders text paragraphs, and the React logo, and the application has no significant UI state changes or complex logic.</p>
<p>Now, let’s bundle this application for production.</p>
<p>Stop the local running server and build the application with the following command:</p>
<pre><code class="lang-js">npm run build
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-12.34.26@2x.png" alt="Building the test React application for production." width="2000" height="1217" loading="lazy">
<em>Building the test React application for production.</em></p>
<p>Let’s take a look at the build output.</p>
<p>Open the <code>test-react-app</code> directory in your code editor of choice and observe the <code>build/index.html</code> file. This root file will be served to the browser when the React application is visited.</p>
<p>Unwrap the minified file:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 build/index.html --&gt;</span>

<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.ico"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width,initial-scale=1"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"theme-color"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"#000000"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span>
      <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span>
      <span class="hljs-attr">content</span>=<span class="hljs-string">"Web site created using create-react-app"</span>
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"apple-touch-icon"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/logo192.png"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"manifest"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/manifest.json"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>React App<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">defer</span>=<span class="hljs-string">"defer"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/static/js/main.3b5961bb.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/static/css/main.073c9b0a.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">noscript</span>&gt;</span>You need to enable JavaScript to run this app.<span class="hljs-tag">&lt;/<span class="hljs-name">noscript</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>This is a standard HTML file. But what’s of note in its content is the following:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 build/index.html --&gt;</span>
... 
<span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">defer</span>=<span class="hljs-string">"defer"</span> <span class="hljs-attr">src</span>=<span class="hljs-string">"/static/js/main.3b5961bb.js"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/static/css/main.073c9b0a.css"</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"stylesheet"</span> /&gt;</span>
... 

<span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"root"</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
...
</code></pre>
<p>The document renders a <code>&lt;div id="root"&gt;&lt;/div&gt;</code> node, and the bundled <code>JS</code> and <code>CSS</code> assets are linked in the <code>&lt;head&gt;</code>.</p>
<p>Do you see the <code>defer</code> attribute on the <code>&lt;script&gt;</code>?</p>
<p>With the <code>defer</code> attribute, the script will be downloaded in parallel as the page is parsed and will be executed after the page is parsed.</p>
<p>By implication, this page renders an empty <code>&lt;div&gt;</code> at first until the JavaScript is parsed.</p>
<p>Well, let’s not panic. Instead, let’s explore the JavaScript referenced here. First, look at the bundled JavaScript asset in <code>build/static/js/main...js</code>.</p>
<p>If we unwrap the minified file, we should have a file that’s a little short of <code>9500</code> lines of JavaScript!</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-12.46.05@2x.png" alt="Unwrapping the minified Javascript asset for the trivial React application." width="2272" height="1950" loading="lazy">
<em>Unwrapping the minified Javascript asset for the trivial React application.</em></p>
<p>Wait … what?! For such a trivial application?! 😱</p>
<p>Oh yes.</p>
<p>I considered adding a funny meme here, but let’s not stray from the point’s importance.</p>
<p>Explaining what goes on within these <code>9000+</code> lines of JavaScript is beyond the scope of this book. But what we have in the file is an immediately invoked function (IIFE) with its entire content executed.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 build/static/js/main...js</span>
!(<span class="hljs-function"><span class="hljs-keyword">function</span> (<span class="hljs-params"></span>) </span>{
  <span class="hljs-comment">// ... lines of code go here</span>
})();
</code></pre>
<p>We certainly didn’t write the <code>9000+</code> lines of code in the <code>main</code> bundle. No! Most of that is the React runtime needed to make our React application work in the way React’s built: state, props, hooks, virtual DOM, and all the lovely abstractions React provides.</p>
<h3 id="heading-ditching-the-runtime">Ditching the runtime</h3>
<p>Unlike most JavaScript frameworks, Astro advocates for zero JavaScript by default. This means no JavaScript runtime overhead, as in the previous React application.</p>
<p>So, I’ve done what any competent investigator would — reconstructed the crime scene.</p>
<p>To do this, I built the same React starter application using Astro.</p>
<p>Use the following command to create the project:</p>
<pre><code class="lang-js">npm create astro@latest -- --template ohansemmanuel/astrojs-ditch-the-runtime-react --yes
</code></pre>
<p>We use the same <code>create astro</code> command to create a new project. The difference here is the <code>--template</code> argument that points to <code>ohansemmanuel/astrojs-ditch-the-runtime-react</code> and the <code>--yes</code> argument to skip all prompts and accept the defaults.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-09-at-07.40.44.png" alt="Creating a new Astro project with a template." width="1142" height="840" loading="lazy">
<em>Creating a new Astro project with a template.</em></p>
<p>Choose the project directory, then start the application via:</p>
<pre><code class="lang-js">npm run start
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-01-14-at-09.31.23@2x.png" alt="The new Astro project running on localhost" width="2000" height="1407" loading="lazy">
<em>The new Astro project running on localhost</em></p>
<p>Note that the application is similar to the starter React application we explored earlier.</p>
<p>Now let’s go ahead and build this application for production with the following command:</p>
<pre><code class="lang-js">npm run build
</code></pre>
<p>This will build the Astro application and generate static in the <code>dist/</code> directory.</p>
<p>Explore the build output and find the main <code>HTML</code>, <code>CSS</code> and image files in <code>dist/assets</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-28-at-13.04.29@2x.png" alt="The Astro project build output." width="2272" height="1760" loading="lazy">
<em>The Astro project build output.</em></p>
<p>Look closely, and you’ll realise there’s no JavaScript build output! Instead, we have the <code>index.html</code> file, associated <code>CSS</code>, and image assets.</p>
<p>For the same result, we’ve eliminated the 9000+ lines of JavaScript the React example required.</p>
<p>This right here is what’s meant by <strong>zero JavaScript by default.</strong> This is the Astro premise.</p>
<p>I’m not advocating that you don’t use React or your favourite framework. But this example helps you understand Astro’s premise, that is to eliminate the need to have such client-side runtime <strong>if you don’t need it.</strong></p>
<p>The exciting truth is that we don’t need the JavaScript runtime overhead for many applications, such as content-driven websites. So you can ditch it in favour of Astro.</p>
<h2 id="heading-what-is-an-astro-component">What is an Astro Component?</h2>
<p>Before defining Astro components, let’s consider a more generic question. In straightforward terms, what is a website?</p>
<p>My straightforward answer would be: a website is a set of related <code>HTML</code> pages under a single domain.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/2.png" alt="A multi page website" width="2046" height="1378" loading="lazy">
<em>A multi page website</em></p>
<p>Now, with a single-page application, my definition would need to be updated. This is because a single-page website now consists of a single <code>HTML</code> page with routing handled via client-side JavaScript.</p>
<p>Regardless of the type of website, there’s a common denominator: the browser renders one or more <code>HTML</code> pages.</p>
<p>So, we will start our discussion by exploring the basic <code>HTML</code> page shown below:</p>
<pre><code class="lang-js">&lt;!DOCTYPE html&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-GB"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>HTML 101<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
      <span class="hljs-selector-tag">p</span> {
        <span class="hljs-attribute">color</span>: red;
      }
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello world'</span>);
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>We won’t win any design awards with this page, but it suffices for our learning purposes.</p>
<p>In the <code>HTML</code> above, notice how we’ve produced a paragraph with the text <code>Hello world</code>, styled it with some <code>CSS</code> and logged a message to the console using <code>JavaScript</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-02-02-at-06.19.40.png" alt="The basic HTML page" width="1325" height="1045" loading="lazy">
<em>The basic HTML page</em></p>
<p>In this seemingly simple file, we’ve combined <code>style</code>, <code>script</code> and <code>markup</code> — the three core components of any web application.</p>
<p>Astro components are identical to HTML files, leading us to our first definition of an Astro component.</p>
<h3 id="heading-an-astro-component-is-a-astro-file-capable-of-rendering-any-valid-html">An Astro component is a <code>.astro</code> file capable of rendering any valid HTML</h3>
<p>An Astro component is a document with a <code>.astro</code> file ending, that is <code>file.astro</code> or <code>anotherFile.astro</code> capable of rendering valid HTML content.</p>
<p>Let’s start a barebones <code>hello-astro</code> project to explore this statement. This time, we will not use the <code>create astro</code> utility. Instead, we will manually install Astro.</p>
<p>Create an empty directory and navigate into it:</p>
<pre><code class="lang-bash">mkdir hello-astro
<span class="hljs-built_in">cd</span> hello-astro
</code></pre>
<p>Run the following command to start the new project:</p>
<pre><code class="lang-js">npm init --yes
</code></pre>
<p>The <code>--yes</code> flag will use all the defaults, skipping the prompts.</p>
<p>Now install <code>astro</code>:</p>
<pre><code class="lang-js">npm install astro
</code></pre>
<p>Create an empty Astro page in the project in <code>src/pages/index.astro</code>.</p>
<p>This file must be in the <code>src/pages</code> directory as <code>pages</code> are the entry point to an Astro project.</p>
<p>Now we should have a project structure similar to the following:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-02-02-at-07.30.52.png" alt="The hello-astro project structure." width="896" height="243" loading="lazy">
<em>The hello-astro project structure.</em></p>
<p>At this point, go ahead and paste the starting <code>HTML</code> snippet into the <code>index.astro</code> component as follows:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/pages/index.astro --&gt;</span>
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-GB"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>HTML 101<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
      <span class="hljs-selector-tag">p</span> {
        <span class="hljs-attribute">color</span>: red;
      }
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello world'</span>);
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Then start up the application with the command:</p>
<pre><code class="lang-html">npx astro dev
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-02-04-at-07.09.03.png" alt="The hello astro application" width="1325" height="1045" loading="lazy">
<em>The hello astro application</em></p>
<p>We’ve got <code>Hello World</code> in red! <code>index.astro</code> successfully renders the <code>HTML</code> content to our web application’s <code>index</code> page.</p>
<p>Valid HTML is thus valid Astro.</p>
<p>If you know HTML, you already know some Astro.</p>
<p>The familiarity with HTML makes Astro approachable. But Astro components would be useless if they were equivalent to <code>HTML</code> pages. Building a new library (Astro) identical to HTML would waste resources. Well, apart from the fancy Astro logo, that’s a win.</p>
<p>Luckily, the Astro component syntax provides features expected from a modern frontend library, making it <strong>a superset of HTML</strong>.</p>
<p>This leads to our second definition.</p>
<h3 id="heading-astro-components-can-be-composed-to-make-complex-pages">Astro components can be composed to make complex pages</h3>
<p>Standard HTML files cannot be composed. We cannot import HTML files into another HTML file. That would be invalid.</p>
<p>But composability is vital to structuring complex user interfaces.</p>
<p>Astro components are composable, which makes them highly flexible and reusable.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/c.png" alt="The parent child component relationship" width="2000" height="1213" loading="lazy">
<em>The parent child component relationship</em></p>
<p>The following pseudocode would be a valid representation of parent-child components:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">AstroComponent</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- render children components in here --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ChildAstroComponent</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ChildAstroComponent</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">ChildAstroComponent</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">AstroComponent</span>&gt;</span>
</code></pre>
<p>The simplified mental model for building classic websites involves stringing together a bunch of HTML pages to make up a website.</p>
<p>Astro builds upon the same mental model.</p>
<p>So, essentially, an Astro website comprises pages that eventually get compiled into <code>HTML</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/c-1.png" alt="A website made of Astro pages." width="2000" height="786" loading="lazy">
<em>A website made of Astro pages.</em></p>
<p>Since Astro pages are just Astro components found in the <code>src/pages</code> directory of our Astro project, they can also compose other Astro components.</p>
<p>Let’s give this a shot.</p>
<p>Consider the starting <code>index.astro</code> page below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂src/pages/index.astro --&gt;</span>

<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-GB"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>HTML 101<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
      <span class="hljs-selector-tag">p</span> {
        <span class="hljs-attribute">color</span>: red;
      }
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">'Hello world'</span>);
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Conceptually, we could compose the <code>index.astro</code> component from two smaller components: <code>Head</code> and <code>Body</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/c-2.png" alt="Composing the index page from the Head and Body components" width="2000" height="2026" loading="lazy">
<em>Composing the index page from the Head and Body components</em></p>
<p>Here’s how:</p>
<pre><code class="lang-js">&lt;!-- 📂 src/pages/index.astro --&gt;
---
<span class="hljs-keyword">import</span> Body <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Body.astro"</span>;
<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Head.astro"</span>;
---

&lt;!DOCTYPE html&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-GB"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Head</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Body</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<ul>
<li>The child components are imported within a code fence <code>---</code></li>
<li>The child components are rendered within the component template, that is <code>&lt;Head /&gt;</code> and <code>&lt;Body /&gt;</code> — similar to self-closing <code>HTML</code> tags.</li>
</ul>
<p>Where <code>Body</code> and <code>Head</code> are as follows:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/Body.astro</span>
&lt;body&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello World<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
&lt;/body&gt;
</code></pre>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/Head.astro </span>
&lt;head&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>HTML 101<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span></span>

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
    <span class="hljs-selector-tag">p</span> {
      <span class="hljs-attribute">color</span>: red;
    }
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>

  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
    <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Hello world"</span>);
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
&lt;/head&gt;
</code></pre>
<p>Note how <code>Head</code> and <code>Body</code> represent “partial” <code>HTML</code> building blocks.</p>
<p>The level of composition we build our pages from is entirely up to us. For example, we could further break down the <code>Head</code> component into smaller bits.</p>
<p>Let’s consider introducing isolated components for the <code>meta</code>, <code>title</code>, <code>style</code> and script elements.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/c-3.png" alt="Composing the Head component from other smaller components" width="2000" height="1445" loading="lazy">
<em>Composing the Head component from other smaller components</em></p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/Head.astro</span>
---
<span class="hljs-keyword">import</span> Meta <span class="hljs-keyword">from</span> <span class="hljs-string">"./Meta.astro"</span>;
<span class="hljs-keyword">import</span> Title <span class="hljs-keyword">from</span> <span class="hljs-string">"./Title.astro"</span>;
<span class="hljs-keyword">import</span> Style <span class="hljs-keyword">from</span> <span class="hljs-string">"./Style.astro"</span>;
<span class="hljs-keyword">import</span> Script <span class="hljs-keyword">from</span> <span class="hljs-string">"./Script.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Meta</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Title</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Style</span> /&gt;</span><span class="xml">
  <span class="hljs-tag">&lt;<span class="hljs-name">Script</span> /&gt;</span><span class="xml">
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span></span></span></span>
</code></pre>
<p>The <code>index</code> page still composes the same top-level components, that is <code>Head</code> and <code>Body</code>. However, <code>Head</code> now contains even more components.</p>
<p>This is the level of composition available to us with many modern frontend libraries. But to prevent unwanted bugs, there are some essential behaviours to be aware of when composing components in Astro.</p>
<h4 id="heading-1-styles-are-local-by-default">1. Styles are local by default</h4>
<p>It is vital to distinguish how Astro behaves when composing components with styles.</p>
<p>For example, we had a red paragraph when we started with all the <code>HTML</code> content in <code>index.astro</code>.</p>
<p>Now we’ve lost the paragraph style after our composition.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-02-04-at-13.04.36.png" alt="The red paragraph style lost after the composition" width="1325" height="1045" loading="lazy">
<em>The red paragraph style lost after the composition</em></p>
<p>What’s gone wrong?</p>
<p>To understand this, we must determine where the style seats in the component composition.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/c-4.png" alt="Styles in Astro components are local by default and do not leak over." width="2000" height="1598" loading="lazy">
<em>Styles in Astro components are local by default and do not leak over.</em></p>
<p>We have the <code>style</code> defined in the <code>Head.astro</code> component and expect it to affect the <code>&lt;p&gt;</code> in the <code>Body.astro</code> component.</p>
<p>This does not work.</p>
<p>This is because, with Astro components, styles are local by default. This means the <code>&lt;style&gt;</code> in <code>Head.astro</code> only affects elements defined in the <code>Head.astro</code> component.</p>
<p>Since the <code>&lt;p&gt;Hello world&lt;/p&gt;</code> lives in a separate component, the styles never leak over.</p>
<h4 id="heading-2-the-html-element-will-always-be-present">2. The HTML element will always be present</h4>
<p>The <code>&lt;html&gt;</code> element represents the top-level element of an HTML document. It is often called the root element. Other elements must be descendants.</p>
<p>Our current <code>index.astro</code> page composition looks like this:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/index.astro</span>
---
<span class="hljs-keyword">import</span> Body <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Body.astro"</span>;
<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Head.astro"</span>;
---

&lt;!DOCTYPE html&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en-GB"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Head</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">Body</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>Every child component is housed in <code>Head</code> and <code>Body</code> and rendered within the root <code>html</code> element.</p>
<p>But what happens if we remove this element (and the associated <code>DOCTYPE</code>) as seen below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/components/index.astro</span>
---
<span class="hljs-keyword">import</span> Body <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Body.astro"</span>;
<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Head.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Head</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Body</span> /&gt;</span></span>
</code></pre>
<p>The <code>HTML</code> page will be rendered with a reasonable default:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- Default HTML wrapper provided --&gt;</span> 
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- Every other component rendered here --&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-01-17-at-06.40.58@2x.png" alt="The rendered page with a reasonable default." width="2000" height="1407" loading="lazy">
<em>The rendered page with a reasonable default.</em></p>
<p>Did you know that according to HTML standards, the use of <code>&lt;html&gt;</code> is optional? This means that even without it, the browser can still render the page with a suitable default. Browsers can even render invalid HTML pages! </p>
<p>That being said, Astro’s default setting allows you to template even invalid HTML. So, be careful.</p>
<p>For accessibility reasons, include an <code>&lt;html&gt;</code> element. This is relevant to providing the <code>lang</code> attribute for the webpage. Again, this is helpful for screen-reading technologies.</p>
<h4 id="heading-3-styles-and-scripts-are-hoisted">3. Styles and scripts are hoisted</h4>
<p>Our page’s <code>&lt;script&gt;</code> and <code>&lt;style&gt;</code> elements exist in the associated <code>Script</code> and <code>Style</code> components.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/c-5.png" alt="The Style and Script child components" width="2000" height="2026" loading="lazy">
<em>The Style and Script child components</em></p>
<p>These child components are also precisely rendered within the <code>Head</code> component, and ultimately, we have a markup with <code>&lt;style&gt;</code> and <code>&lt;script&gt;</code> in <code>&lt;head&gt;</code>.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span> ... <span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span> ... <span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>/&gt;</span>
</code></pre>
<p>As previously mentioned, <code>HTML</code> is quite lenient and will even attempt to render invalid HTML markup. But the <code>&lt;style&gt;</code> element must be included in the <code>&lt;head&gt;</code> of an <code>HTML</code> document.</p>
<p>Let’s attempt to break this rule.</p>
<p>Change <code>index.astro</code> to have <code>Style</code> and <code>Script</code> as adjacent sibling components to <code>Head</code>:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> Body <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Body.astro"</span>;
<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Head.astro"</span>;
<span class="hljs-keyword">import</span> Style <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Style.astro"</span>;
<span class="hljs-keyword">import</span> Script <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Script.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Head</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Body</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Style</span> /&gt;</span></span>
<span class="xml"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Script</span> /&gt;</span></span></span>
</code></pre>
<p>Instead of rendering <code>Style</code> and <code>Script</code> within the <code>&lt;head&gt;</code> of the document, we’ve placed them adjacent to the <code>&lt;head&gt;</code> and <code>&lt;body&gt;</code> elements.</p>
<p>From the composition above, you may expect a render markup similar to the following:</p>
<pre><code class="lang-js">&lt;head&gt; ... &lt;head&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span> .... <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span> ... <span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span> ... <span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>But inspect the rendered Astro page, and you’ll find the <code>style</code> and <code>script</code> elements still placed within the <code>&lt;head&gt;</code> of the document.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-02-04-at-13.50.39.png" alt="The hoisted script and style elements" width="1325" height="1045" loading="lazy">
<em>The hoisted script and style elements</em></p>
<p>This is because in Astro, we can freely use the <code>&lt;style&gt;</code> and <code>&lt;script&gt;</code> elements within our components, and they’ll be hoisted to the <code>&lt;head&gt;</code> of the rendered document. This is regardless of the component composition.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/c-6.png" alt="<style> and <script> are hoisted to the <head> of our page" width="2000" height="1255" loading="lazy">
<em>&lt;style&gt; and &lt;script&gt; are hoisted to the &lt;head&gt; of our page</em></p>
<p>As we’ll learn later, there’s an exception to this behaviour with inline scripts.</p>
<h4 id="heading-4-the-element-and-its-children-will-not-be-hoisted">4. The  element and its children will not be hoisted</h4>
<p>Seeing how <code>&lt;style&gt;</code> and <code>&lt;script&gt;</code> elements are hoisted may tempt you to use a <code>&lt;head&gt;</code> element incorrectly in your component composition.</p>
<p>But note that the <code>&lt;head&gt;</code> element and its children will not be hoisted, that is it does not get moved to the top of the page or merged with an existing <code>&lt;head&gt;</code>.</p>
<p>Let’s add a new adjacent <code>&lt;head&gt;</code> element:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/index.astro</span>
---
<span class="hljs-keyword">import</span> Body <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Body.astro"</span>;
<span class="hljs-keyword">import</span> Head <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Head.astro"</span>;
<span class="hljs-keyword">import</span> Style <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Style.astro"</span>;
<span class="hljs-keyword">import</span> Script <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Script.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Head</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Body</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Style</span> /&gt;</span></span>
<span class="xml"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Script</span> /&gt;</span></span></span>
<span class="xml"><span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">property</span>=<span class="hljs-string">"og:type"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"article"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span></span></span>
</code></pre>
<p>Adding a new <code>&lt;head&gt;</code> element to the bottom of the page is a silly composition. But browsers are forgiving of bad <code>HTML</code> markup, so in this case, the extra <code>&lt;head&gt;</code> element is ignored, and its content is rendered within the <code>&lt;body&gt;</code> element of the page.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-01-17-at-07.50.01@2x.png" alt="The browser trying to make sense of the wrong composition" width="2000" height="1407" loading="lazy">
<em>The browser trying to make sense of the wrong composition</em></p>
<p>Always have the <code>&lt;head&gt;</code> page elements in a layout component to prevent unwanted behaviours. This is a recommended best practice.</p>
<h3 id="heading-astro-components-can-leverage-a-powerful-templating-syntax">Astro components can leverage a powerful templating syntax</h3>
<p>Templating is at the heart of most beloved frontend libraries. Think React and JSX or Vue and Vue templates.</p>
<p>Astro isn’t different.</p>
<p>Astro provides powerful templating by splitting a component into two main parts: the component script and the component template sections.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/c-7.png" alt="The make-up of an Astro component" width="2000" height="2026" loading="lazy">
<em>The make-up of an Astro component</em></p>
<p>It is important to note that technically, an Astro component is still valid with one or none of the sections present, that is an empty (yet valid) Astro component will have none of these sections.</p>
<h4 id="heading-component-script">Component script</h4>
<p>The component script section is identified with a code fence <code>(---)</code>.</p>
<pre><code class="lang-js">--- 
  <span class="hljs-comment">// This is the component script section </span>
---
</code></pre>
<p>Typically, the component script section is where we write the JavaScript code we need to reference within our template.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/c-8.png" alt="Leverage values from the component script section in the component template" width="2000" height="1394" loading="lazy">
<em>Leverage values from the component script section in the component template</em></p>
<p>Remember that when our Astro component is eventually compiled, the JavaScript expressions in the script section are evaluated at build time. Therefore, the JavaScript values are used to generate the eventual <code>HTML</code> pages once.</p>
<p>The component script section is not the place for dynamic interactive JavaScript code.</p>
<p>That being said, there are three main actions we’ll be performing in the component script section.</p>
<p>Let’s take a look at these.</p>
<h5 id="heading-1-creating-or-referencing-variables">1. Creating or referencing variables</h5>
<p>We may need to create variables for various reasons, for example to keep our markup DRY (don’t repeat yourself). In addition, the component script section supports standard JavaScript and TypeScript code. So creating or referencing variables works as we would expect.</p>
<pre><code class="lang-js">--- 
<span class="hljs-comment">// Javascript</span>
<span class="hljs-keyword">const</span> newVariable = <span class="hljs-string">"This is a new variable"</span>
<span class="hljs-comment">// Typescript</span>
<span class="hljs-keyword">let</span> newVar: string = <span class="hljs-string">"This is a new var"</span>;
newVar = <span class="hljs-number">9</span>;
---
</code></pre>
<p>If the IDE is setup for TypeScript, we’ll get a warning within the editor when we try the reassign the <code>newVar</code> variable to a number:</p>
<pre><code class="lang-js">Type <span class="hljs-string">'number'</span> is not assignable to type <span class="hljs-string">'string'</span>.
</code></pre>
<p>TypeScript is supported in the component script section by default.</p>
<p>Components are also capable of receiving props. Props are HTML-like attributes passed when we render a component. For example, here is a name prop passed to a <code>MyAstroComponent</code> component:</p>
<pre><code class="lang-js">&lt;MyAstroComponent name=<span class="hljs-string">"Emmanuel"</span>/&gt;
</code></pre>
<p>Within the component script section, props passed to a component may be referenced on the <code>Astro.props</code> global as shown below:</p>
<pre><code class="lang-js">&lt;!-- 📂 MyAstroComponent.astro --&gt;
---
<span class="hljs-keyword">const</span> { name } = Astro.props 
---
</code></pre>
<p>Since TypeScript is valid within the component script section, we can also type a component’s prop.</p>
<p>To provide prop types, go ahead and define a <code>Props</code> interface or type alias in the component script section:</p>
<pre><code class="lang-js">---
<span class="hljs-comment">// ✅ This is valid </span>
type Props = {
  <span class="hljs-attr">name</span>: string 
}
---
</code></pre>
<pre><code class="lang-js">---
<span class="hljs-comment">// ✅ This is equally valid </span>
interface Props {
  <span class="hljs-attr">name</span>: string 
}
---
</code></pre>
<p>Astro will automatically pick up the defined <code>Props</code> type and give relevant type warnings/errors related to wrong component props usage.</p>
<h5 id="heading-2-handling-imports">2. Handling imports</h5>
<p>At the start of most JavaScript modules lie imports. Astro components are not any different.</p>
<p>Composing multiple Astro components to build complex pages typically means importing other components or leveraging modules required to get our page working as expected.</p>
<p>Out of the box, Astro supports a wide range of file types, namely:</p>
<ul>
<li>Astro Components (<code>.astro</code>)</li>
<li>Markdown (<code>.md</code>, <code>.markdown</code>, and so on)</li>
<li>JavaScript (<code>.js</code>, <code>.mjs</code>)</li>
<li>TypeScript (<code>.ts</code>, <code>.tsx</code>)</li>
<li>NPM Packages</li>
<li>JSON (<code>.json</code>)</li>
<li>JSX (<code>.jsx</code>, <code>.tsx</code>)</li>
<li>CSS (<code>.css</code>)</li>
<li>CSS Modules (<code>.module.css</code>)</li>
<li>Images &amp; Assets (<code>.svg</code>, <code>.jpg</code>, <code>.png</code>, and so on)</li>
</ul>
<p>That’s a lot of file types supported natively! Here are some examples of import statements:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Astro </span>
<span class="hljs-keyword">import</span> Book <span class="hljs-keyword">from</span> <span class="hljs-string">'./book.astro'</span>

<span class="hljs-comment">// Javascript </span>
<span class="hljs-keyword">import</span> { getUnderstandingAstro } <span class="hljs-keyword">from</span> <span class="hljs-string">'./book.js'</span>; 

<span class="hljs-comment">// Typescript</span>
<span class="hljs-keyword">import</span> { getUser } <span class="hljs-keyword">from</span> <span class="hljs-string">'./book'</span>; 
<span class="hljs-keyword">import</span> type { UserType } <span class="hljs-keyword">from</span> <span class="hljs-string">'./book'</span>; 

<span class="hljs-comment">// NPM package </span>
<span class="hljs-keyword">import</span> { v4 <span class="hljs-keyword">as</span> uuidv4 } <span class="hljs-keyword">from</span> <span class="hljs-string">'uuid'</span>;

<span class="hljs-comment">// load JSON via default export</span>
<span class="hljs-keyword">import</span> json <span class="hljs-keyword">from</span> <span class="hljs-string">'./data.json'</span>; 

<span class="hljs-comment">// load and inject style onto the page</span>
<span class="hljs-keyword">import</span> <span class="hljs-string">'./style.css'</span>; 

<span class="hljs-comment">// css modules </span>
<span class="hljs-keyword">import</span> styles <span class="hljs-keyword">from</span> <span class="hljs-string">'./style.module.css'</span>; 

<span class="hljs-comment">// other assets</span>
<span class="hljs-keyword">import</span> imgReference <span class="hljs-keyword">from</span> <span class="hljs-string">'./image.png'</span>; 
<span class="hljs-keyword">import</span> svgReference <span class="hljs-keyword">from</span> <span class="hljs-string">'./image.svg'</span>; 
<span class="hljs-keyword">import</span> txtReference <span class="hljs-keyword">from</span> <span class="hljs-string">'./words.txt'</span>;
</code></pre>
<p>The important point to note here is apart from TypeScript files and NPM packages, we typically need to add the file ending to the Astro import statement, for example:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ✅ do this </span>
<span class="hljs-keyword">import</span> Book <span class="hljs-keyword">from</span> <span class="hljs-string">'./book.astro'</span>

<span class="hljs-comment">// ❌ not this </span>
<span class="hljs-keyword">import</span> Book <span class="hljs-keyword">from</span> <span class="hljs-string">'./book'</span>
</code></pre>
<p>Astro also supports importing components from other UI frameworks such as React, Vue, Svelte, and so on. An example import for a React component would look like this:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { Header } <span class="hljs-keyword">from</span> <span class="hljs-string">'./Header.jsx'</span>
<span class="hljs-comment">// if file ending is .tsx</span>
<span class="hljs-keyword">import</span> { Header } <span class="hljs-keyword">from</span> <span class="hljs-string">'./Header'</span>
</code></pre>
<p>We will explore these in a later chapter.</p>
<p>It’s equally important to note that we can import any asset from the <code>public</code> directory. But note that assets in the <code>public</code> directory will remain untouched by Astro, that is they will be copied as is into the final build without processing (for example, minification).</p>
<pre><code class="lang-js"><span class="hljs-comment">// image in public/img-public.png</span>
<span class="hljs-keyword">import</span> imageRef <span class="hljs-keyword">from</span> <span class="hljs-string">"/img-public.png"</span>;
</code></pre>
<p>As a matter of best practice, favour placing images within the <code>src</code> directory so Astro can transform, optimise, and bundle them where possible. The exception is images in markdown (<code>.md</code>) files.</p>
<p>Images within <code>src</code> won’t work in markdown files, so use the <code>public</code> directory or a remote <code>src</code> URL as shown below:</p>
<pre><code class="lang-md">// my-nice-blog.md

![<span class="hljs-string">A wonderful photo of a cat</span>](<span class="hljs-link">/photo-in-public-dir.png</span>)
![<span class="hljs-string">Another cat photo</span>](<span class="hljs-link">https://www.photos.com/this-is-a-cat.png</span>)
</code></pre>
<h5 id="heading-3-fetching-data">3. Fetching data</h5>
<p>Astro components can utilise the global <code>fetch</code> function to establish HTTP requests to remote APIs from the component script section. The fetched data can subsequently be accessed within the component template.</p>
<pre><code class="lang-js">---
{<span class="hljs-comment">/** Random user generator **/</span>}
<span class="hljs-keyword">const</span> URL = <span class="hljs-string">"https://random-data-api.com/api/users/random_user?size=1"</span>
<span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(URL)
<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json()
---

<span class="hljs-comment">// Use data in the template </span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">pre</span>&gt;</span>{JSON.stringify(data, null, 2)}<span class="hljs-tag">&lt;/<span class="hljs-name">pre</span>&gt;</span></span>
</code></pre>
<p>The API call will only be made once for statically generated Astro sites to build the <code>HTML</code> page.</p>
<p>But while developing locally, the API requests in the component script section are fetched every time on page refresh. This is only a development behaviour. In our example, we will get a new random user on every page refresh.</p>
<p>Run the production build with <code>npm run build</code> and preview the production application with <code>npm run preview</code> to see the standard behaviour in action. We will have a single user on every page refresh, that is the user fetched at build time.</p>
<h4 id="heading-component-template">Component template</h4>
<p>The variables created, imports made, and data fetched in the component script section exist primarily for one reason: to be consumed in the component template section of the component.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/d.png" alt="Consuming variables in the component template section" width="2000" height="2026" loading="lazy">
<em>Consuming variables in the component template section</em></p>
<p>If Astro components are eventually built to <code>HTML</code>, the template section defines the markup of the said <code>HTML</code> page. But the component template section lets us do this dynamically, that is by leveraging the power of JavaScript expressions.</p>
<p>Let’s explore some of the actions we’re likely to perform within the component template of an Astro component.</p>
<h5 id="heading-consuming-variables">Consuming variables</h5>
<p>To consume a variable, wrap the name of the variable in curly braces as shown below:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> book = <span class="hljs-string">"Understanding AstroJS"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{book}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span> <span class="hljs-comment">// Outputs &lt;h1&gt;Understanding AstroJS&lt;/h1&gt;</span>
</code></pre>
<h5 id="heading-create-dynamic-attributes">Create dynamic attributes</h5>
<p>Creating a dynamic attribute is similar to consuming a variable. Use the variable in curly braces to pass attributes to both HTML elements and components:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> { author } = Astro.props;
<span class="hljs-keyword">const</span> book = <span class="hljs-string">"Understanding AstroJS"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span> <span class="hljs-attr">data-name</span>=<span class="hljs-string">{book}</span>&gt;</span>A new book<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span> 
<span class="hljs-comment">// Outputs &lt;h1 data-name="Understanding AstroJS"&gt;A new book&lt;/h1&gt;</span>
</code></pre>
<h5 id="heading-dynamic-html">Dynamic HTML</h5>
<p>Dynamic HTML is quite the lifesaver as we’ll occasionally not want to repeat ourselves. For example, consider how we may create dynamic lists as shown below:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> technologies = [<span class="hljs-string">'Javascript'</span>, <span class="hljs-string">'Typescript'</span>, <span class="hljs-string">'NodeJS'</span>]
---
<span class="hljs-comment">// Dynamically create a list of elements from technologies</span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span> 
  {items.map((item) =&gt; <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>{item}<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>)}
<span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span></span>
</code></pre>
<p>Or we may find ourselves in need of conditional rendering. To do this, leverage logical operators and ternary expressions as shown below:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> showCallToAction = <span class="hljs-literal">true</span>;
---

<span class="hljs-comment">// This will render &lt;button&gt;Buy now&lt;/button&gt;</span>
{showCallToAction &amp;&amp; <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Buy now<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span>} 

<span class="hljs-comment">// Alternatively, represent this with a ternary to provide a fallback</span>
{showCallToAction ?  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">button</span>&gt;</span>Buy now<span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span></span> : <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Continue
 shopping<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>}
</code></pre>
<p>This will render <code>&lt;button&gt;Buy now&lt;/button&gt;</code> when <code>showCallToAction</code> is truthy and <code>&lt;p&gt;Continue shopping&lt;/p&gt;</code> otherwise.</p>
<h5 id="heading-dynamic-tags">Dynamic Tags</h5>
<p>Less commonly used, dynamic tags can still be useful in certain situations, such as building polymorphic components. </p>
<p>Depending on the consumer’s prop input, these components can render to various element nodes. An example is the <code>Text.astro</code> component that can render any element passed to it:</p>
<pre><code class="lang-js"><span class="hljs-comment">// usage </span>
&lt;Text <span class="hljs-keyword">as</span>=<span class="hljs-string">"h1"</span> /&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Text</span> <span class="hljs-attr">as</span>=<span class="hljs-string">"div"</span> /&gt;</span></span>
</code></pre>
<p>In both cases, we want to render the same component with different underlying HTML element nodes, that is <code>h1</code> and <code>div</code> text nodes.</p>
<p>We can handle this dynamically, as shown below:</p>
<pre><code class="lang-js">&lt;!-- 📂 Text.astro --&gt;
---
<span class="hljs-keyword">const</span> { <span class="hljs-attr">as</span>: As = <span class="hljs-string">"h1"</span> } = Astro.props;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">As</span>&gt;</span>Text content<span class="hljs-tag">&lt;/<span class="hljs-name">As</span>&gt;</span></span>
</code></pre>
<p>Within the component script section, we deconstruct the <code>as</code> prop and rename it to a capitalised variable <code>As</code>. This is important as the variable names for a dynamically rendered component must be capitalised, that is:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ✅ Do this </span>
&lt;As&gt;Text content&lt;/As&gt;

<span class="hljs-comment">// ❌ not this </span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">as</span>&gt;</span>Text content<span class="hljs-tag">&lt;/<span class="hljs-name">as</span>&gt;</span></span>
</code></pre>
<p>If we pass a lower cased variable, Astro will try to render the variable name as a literal <code>HTML</code> tag. In our example, <code>&lt;as&gt;Text content&lt;/as&gt;</code> and not the dynamic <code>&lt;h1&gt;Text content&lt;/h1&gt;</code> or <code>&lt;div&gt;Text content&lt;/div&gt;</code> element.</p>
<h5 id="heading-revisiting-slots">Revisiting Slots</h5>
<p>If you want to easily add external HTML content to your component template, the <code>&lt;slot /&gt;</code> element is your friend! Any child elements you include will be automatically rendered in a component’s <code>&lt;slot /&gt;</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/slot.png" alt="Using the <slot/> element." width="2000" height="643" loading="lazy">
<em>Using the &lt;slot/&gt; element.</em></p>
<p>If we had a basic <code>Main</code> component with a slot as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/main.astro</span>
--- 
--- 

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
</code></pre>
<p>The child elements of <code>Main</code> will be rendered in the <code>&lt;slot /&gt;</code> as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
---
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This will be rendered in the slot <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Main</span>&gt;</span></span>
</code></pre>
<p>We can also provide fallback <code>&lt;slot&gt;</code> content when no child elements are passed to the component. To do this, provide the <code>&lt;slot /&gt;</code> its own children as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/main.astro</span>
--- 
--- 

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This paragraph will be rendered if no child elements are passed to Main<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">slot</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
</code></pre>
<p>It is possible to provide more than one slot via named slots. Consider the following example:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/main.astro</span>
--- 
--- 

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> This is header <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is an INTRO paragraph <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"after-intro"</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">footer</span>&gt;</span> <span class="hljs-symbol">&amp;copy;</span> 2023 <span class="hljs-tag">&lt;/<span class="hljs-name">footer</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"after-footer"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">main</span>&gt;</span></span>
</code></pre>
<p>In this case, we can render specific child elements to the specific slots <code>after-intro</code> and <code>after-footer</code> as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
---
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Main</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"after-intro"</span>&gt;</span>Hello after Intro<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This will be rendered in the default (nameless) slot <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  {/** This will be rendered in the after-footer slot **/}
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"after-footer"</span>&gt;</span>Download my new book <span class="hljs-tag">&lt;/&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">Main</span>&gt;</span></span>
</code></pre>
<h5 id="heading-not-quite-jsx">Not quite JSX</h5>
<p>Astro’s syntax will feel very familiar to React developers because it is designed to feel similar to HTML and JSX. But there are significant differences to be aware of so we don’t shoot ourselves in the foot.</p>
<p>All <code>HTML</code> attributes in <code>JSX</code> use <code>camelCase</code> formats. In Astro, stick to the standard <code>kebab-case</code> format:</p>
<pre><code class="lang-js">
&lt;!-- JSX --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"foo"</span> <span class="hljs-attr">dataValue</span>=<span class="hljs-string">"bar"</span> /&gt;</span></span>

&lt;!-- Astro --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"foo"</span> <span class="hljs-attr">data-value</span>=<span class="hljs-string">"bar"</span> /&gt;</span></span>
</code></pre>
<p>Unlike <code>JSX</code>, use <code>class</code>, not <code>className</code>.</p>
<p>In Astro, we can also use standard JavaScript or HTML comments:</p>
<pre><code class="lang-js">---
<span class="hljs-comment">//This is a comment</span>
---
&lt;!-- HTML-style comment --&gt;
{<span class="hljs-comment">/* JS style comment also valid */</span>}
</code></pre>
<p>Both are valid in Astro components. But in JSX, only JavaScript-style comments are supported.</p>
<p>With Astro, it is essential to note that HTML-style comments will be included in the browser DOM upon building the page. But JavaScript-style comments will be skipped. As such, for development-only comments, prefer the use of JavaScript-style comments.</p>
<p>My favourite difference is we can use the attribute shorthand for identically named variables in Astro, for example:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> name = <span class="hljs-string">"Understanding astro"</span>
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">MyComponent</span> {<span class="hljs-attr">name</span>} /&gt;</span></span> 

<span class="hljs-comment">// This is identical to writing &lt;MyComponent name={name}&gt;</span>
</code></pre>
<p>This shorthand is not supported in JSX.</p>
<p>Astro and JSX also differ in how whitespaces are treated. Astro follows the HTML rules as closely as possible. But unlike JSX, whitespaces are not escaped.</p>
<pre><code class="lang-js"><span class="hljs-comment">// ❌ will render span (string) with extra whitespace(s)</span>
&lt;span&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span></span>
&lt;/span&gt;

<span class="hljs-comment">// ✅ will add no extra character spaces</span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span></span>
</code></pre>
<p>In most cases, this isn’t very important except when you don’t want that space there! For example, with coloured text backgrounds.</p>
<p>Consider the <code>Code.astro</code> component shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/Code.astro</span>
---
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">code</span> {
    <span class="hljs-attribute">background-color</span>: red;
    <span class="hljs-attribute">color</span>: wheat;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre>
<p>Including the <code>Code</code> component within a paragraph will result in highlighted white spaces.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/white-space.png" alt="Extra white spaces in coloured text backgrounds." width="1984" height="529" loading="lazy">
<em>Extra white spaces in coloured text backgrounds.</em></p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">import</span> Code <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Code.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Use an <span class="hljs-tag">&lt;<span class="hljs-name">Code</span>&gt;</span>if<span class="hljs-tag">&lt;/<span class="hljs-name">Code</span>&gt;</span> statement. Displaying a list? Try array <span class="hljs-tag">&lt;<span class="hljs-name">Code</span>&gt;</span>map()<span class="hljs-tag">&lt;/<span class="hljs-name">Code</span>&gt;</span>.<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre>
<p>To prevent this, change the <code>Code</code> component render to ignore white spaces:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ✅ will add no extra character spaces</span>
&lt;span&gt;<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span></span>&lt;/span&gt;
</code></pre>
<p>And that’s it!</p>
<h2 id="heading-wrapping-up-this-chapter-1">Wrapping Up This Chapter</h2>
<p>Put these together, and we now have a solid definition for an Astro component: a document with a .<code>astro</code> file ending representing a composable superset of HTML. It also provides a powerful templating syntax and renders to HTML with no Javascript runtime overhead.</p>
<p>Wow, if I were to ask a candidate about an Astro component definition in an interview and they gave me this answer, I would knight them on the spot! The job is theirs.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-135.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chapter three.</em></p>
<h1 id="heading-chapter-3-build-your-own-component-island-1">Chapter 3: Build Your Own Component Island</h1>
<blockquote>
<p>“What I cannot create, I do not understand” — Richard Feynman</p>
</blockquote>
<p>Astro’s fast narrative relies on component islands, which allows you to use other framework components like React, Vue, or Svelte in your Astro applications. This chapter will guide us in creating our own component island from the ground up.</p>
<p>To view the complete application, see the <a target="_blank" href="https://github.com/understanding-astro/build-your-own-component-island">GitHub repo</a>. </p>
<h2 id="heading-what-youll-learn-2">What You’ll Learn</h2>
<ul>
<li>An overview of different web application rendering techniques.</li>
<li>Build your own component islands implementation from scratch.</li>
<li>Comprehend the island architecture.</li>
</ul>
<h2 id="heading-a-brief-history-of-how-we-got-here">A Brief History of How We Got Here</h2>
<p>To ensure the coming technical implementation is built on a solid understanding, let’s peep into the past and explore the several application rendering techniques we may employ on a frontend application.</p>
<p>It is essential to note that this isn’t an exhaustive guide to front-end application rendering. But you'll learn enough to understand and appreciate the component islands architecture.</p>
<h3 id="heading-where-it-all-begins">Where it all begins</h3>
<p>In simple terms, there are two main actors in serving an application to a user:</p>
<ol>
<li>The user client, for example a web browser</li>
<li>The application server</li>
</ol>
<p>To display a website, a user requests a resource from an application server.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/a-5.png" alt="The web browser requesting article.html from an application server" width="2000" height="526" loading="lazy">
<em>The web browser requesting article.html from an application server</em></p>
<p>With these two actors at play, a significant architectural decision you’ll make when building any decent frontend application is whether to render an application on the client or server.</p>
<p>Let’s briefly explore both options.</p>
<h3 id="heading-client-side-rendering-csr">Client-side rendering (CSR)</h3>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/1.png" alt="Choosing client side rendering." width="2000" height="990" loading="lazy">
<em>Choosing client side rendering.</em></p>
<p>By definition, a client-side rendered application renders pages directly in the browser using JavaScript. All logic, data-fetching, templating and routing are handled on the client (the user’s browser).</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/a-1.png" alt="An overview of a client-side rendered application." width="2000" height="1230" loading="lazy">
<em>An overview of a client-side rendered application.</em></p>
<p>The past years saw the rise of client-side rendering, particularly among single-page applications. You’ve likely seen this in action if you’ve worked with libraries like React or Vue.</p>
<p>For a practical overview, consider the webpage for a blog article with a like count and a comment section below the initial viewport.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/a-2.png" alt="A blog article with a dynamic sidebar and a comment section below the article." width="2000" height="1286" loading="lazy">
<em>A blog article with a dynamic sidebar and a comment section below the article.</em></p>
<p>If this application was entirely client-side rendered, the simplified rendering flow would look like this:</p>
<ol>
<li>The user visits your website.</li>
<li>Your static server returns a near-empty <code>HTML</code> page to the browser.</li>
<li>The browser fetches the linked script file in the <code>HTML</code> page.</li>
<li>The JavaScript is loaded and parsed.</li>
<li>The data for the article, number of comments, and comments are fetched.</li>
<li>A fully interactive page is shown to the user.</li>
</ol>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/a-3.png" alt="Visualising the rendering process from a user's perspective." width="2000" height="2899" loading="lazy">
<em>Visualising the rendering process from a user's perspective.</em></p>
<h4 id="heading-the-pros-of-client-side-rendering-csr">The pros of client-side rendering (CSR)</h4>
<ul>
<li>The user gets back the resource from the server quickly. In our case, a near-empty <code>HTML</code> page, but on the bright side, the user receives that quickly! In technical terms, client-side rendering yields a high time to first byte (<strong>TTFB</strong>).</li>
<li>Arguably accessible to reason about. All logic, data-fetching, templating and routing are handled in one place – the client.</li>
</ul>
<h4 id="heading-the-cons-of-client-side-rendering">The cons of client-side rendering</h4>
<ul>
<li>It potentially takes the user a long time to see anything tangible on our page, that is they’re initially met with an empty screen. Even if we change the initial <code>HTML</code> page sent to the browser to be an empty application shell, it still potentially takes time for the user to see eventual data, that is after the Javascript is parsed and the data fetched from the server.</li>
<li>As the application grows, the amount of JavaScript parsed and executed before displaying data increases. This can impact mobile performance negatively.</li>
<li>The page's time to interactivity (<strong>TTI</strong>) suffers, for example it takes a long time before our users can interact with the comments. All JavaScript must be parsed, and all associated data must be fetched first.</li>
<li>Detrimental SEO if not implemented correctly.</li>
</ul>
<h3 id="heading-server-side-rendering">Server-side rendering</h3>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/choosing-ssr.png" alt="Choosing server-side rendering." width="2000" height="999" loading="lazy">
<em>Choosing server-side rendering.</em></p>
<p>Let’s assume we’re unhappy with client-side rendering and decide to do the opposite.</p>
<p>On the opposing end of the rendering pole lies server-side rendering.</p>
<p>In a server-side rendered application, a user navigates to our site, and the server generates the full <code>HTML</code> for the page and sends it back to the user.</p>
<p>In our example, here’s what a simplified flow would look like:</p>
<ol>
<li>The user visits our website.</li>
<li>The data for the article, user profile, and comments are fetched on the server.</li>
<li>The server renders the <code>HTML</code> page with the article, the number of comments, and other required assets.</li>
<li>The server sends the client a fully formed <code>HTML</code> page.</li>
</ol>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/aa.png" alt="Visualising the rendering process from a user's perspective." width="2000" height="1844" loading="lazy">
<em>Visualising the rendering process from a user's perspective.</em></p>
<p>NB: it is assumed that the server sends a mostly static <code>HTML</code> page with minimal JavaScript needed for interactivity.</p>
<h4 id="heading-the-pros-of-server-side-rendering">The pros of server-side rendering</h4>
<ul>
<li>As soon as the user browser receives our fully formed <code>HTML</code> page, they can almost immediately interact with it, for example the rendered comments. There’s no need to wait for more JavaScript to be loaded and parsed. In performance lingo, the time to interactivity (<strong>TTI</strong>) equals the first contentful paint (<strong>FCP</strong>).</li>
<li>Great SEO benefits as search engines can index your pages and crawl them just fine.</li>
</ul>
<h4 id="heading-the-cons-of-server-side-rendering">The cons of server-side rendering</h4>
<ul>
<li>Generating pages on the server takes time. In our case, we must wait for all the relevant data to be fetched on the server. As such, the time to first byte (<strong>TTFB</strong>) is slow.</li>
<li>Resource intensive: the server takes on the burden of rendering content for users and bots. As a result, associated server costs increase as rendering needs to be done on the server.</li>
<li>Full page reloads for every requested server resource.</li>
</ul>
<h3 id="heading-server-side-rendering-with-client-side-hydration">Server-side rendering with client-side hydration</h3>
<p>We’ve explored rendering on both sides of the application rendering pole. But what if there was a way to use server and client-side rendering? Some strategy right in the middle of the hypothetic rendering pole?</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/ssr-with-client-rehydration.png" alt="Choosing SSR with client-side hydration." width="2000" height="350" loading="lazy">
<em>Choosing SSR with client-side hydration.</em></p>
<p>If we were building an interactive application and working with a framework like React or Vue, a widely common approach is to render on the server and hydrate on the client.</p>
<p>Hydration, in layperson’s terms, means re-rendering the entire application again on the client to attach event handlers to the DOM and support interactivity.</p>
<p>In theory, this is supposed to give us the wins of server-side rendering plus the interactivity we get with rich client-side rendered applications.</p>
<p>In our example, here’s what a simplified flow would look like:</p>
<ol>
<li>The user visits our website.</li>
<li>The data for the article, user profile, and comments are fetched on the server.</li>
<li>The server renders the <code>HTML</code> page with the article, the number of comments, and other required assets.</li>
<li>The server sends the client a fully formed <code>HTML</code> page alongside the JavaScript client runtime.</li>
<li>The client then “boots up” JavaScript to make the page interactive.</li>
</ol>
<p>Making an otherwise static page interactive (for example, attaching event listeners) is called hydration.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/ssr-csr-hydrate-flow.png" alt="Visualising the rendering process from a user's perspective." width="2000" height="2859" loading="lazy">
<em>Visualising the rendering process from a user's perspective.</em></p>
<h4 id="heading-the-pros-of-server-side-rendering-with-client-side-hydration">The pros of server-side rendering with client-side hydration</h4>
<ul>
<li>Benefits of SSR, for example quick FP and FMP</li>
<li>Can power highly interactive applications.</li>
<li>Supported rendering style in most frontend frameworks such as React and Vue.</li>
</ul>
<h4 id="heading-the-cons-of-server-side-rendering-with-client-side-hydration">The cons of server-side rendering with client-side hydration</h4>
<ul>
<li>Slow time to first byte — similar to standard SSR.</li>
<li>It can delay time to Interactivity (TTI) by making the user interface look ready before completing client-side processing. The period where the UI looks ready but is unresponsive (not hydrated) is what’s been — quite hilariously — dubbed the uncanny valley.</li>
</ul>
<p>NB: this assumes certain parts of our application, such as the likes and comments, can be interacted with, for example clicked to perform further action.</p>
<h3 id="heading-partial-hydration-for-the-win">Partial hydration for the win</h3>
<p>Combining server-side rendering with client-side hydration has the potential to offer the best of both worlds. But it is not without its demerits.</p>
<p>One way to tackle the heavy delay in time to interactivity (TTI) seems clear. Instead of hydrating the entire application, why not hydrate only the interactive bits?</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/p-hydration.png" alt="Partial hydration vs full-page hydration." width="899" height="656" loading="lazy">
<em>Partial hydration vs full-page hydration.</em></p>
<p>As opposed to hydrating the entire application client side, partial hydration refers to hydrating specific parts of an application while leaving the rest static.</p>
<p>For example, in our application, we’d leave the rest of the page static while hydrating just the like button and comment section.</p>
<p>We may also take partial hydration further and implement what’s known as lazy hydration. For example, our application has a comment section below the initial viewport.</p>
<p>In this case, we may hydrate the like button when the page is loaded and hydrate the comment section only when the user scrolls below the initial viewport.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/a-4.png" alt="Hydrate the comment section at a later time." width="2000" height="1286" loading="lazy">
<em>Hydrate the comment section at a later time.</em></p>
<p>Talk about flexibility!</p>
<h4 id="heading-the-pros-of-partial-hydration">The pros of partial hydration</h4>
<ul>
<li>The same benefits of server-side rendering with client-side hydration.</li>
<li>Faster time to interactivity as the entire application isn’t hydrated.</li>
</ul>
<h4 id="heading-the-cons-of-partial-hydration">The cons of partial hydration</h4>
<ul>
<li>If most of the parts of the application are interactive and have a high priority, the advantage of partial hydration could be arguably minimal, that is the entire application would take just as long to be hydrated.</li>
</ul>
<h3 id="heading-where-does-the-island-architecture-come-from">Where does the island architecture come from?</h3>
<p>The island architecture is built upon the foundation of partial hydration. Essentially, the islands architecture refers to having “islands of interactivity” on an otherwise static <code>HTML</code> page.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/independent-islands.png" alt="Islands of interactivity on an otherwise static webpage." width="3103" height="2800" loading="lazy">
<em>Islands of interactivity on an otherwise static webpage.</em></p>
<p>To make sense of this, think of these islands as partially hydrated components. So our entire page isn’t hydrated, but rather these islands.</p>
<h2 id="heading-how-to-implement-a-partial-hydration-islands-architecture">How to Implement a Partial Hydration Islands Architecture</h2>
<p>It’s game time, mate.</p>
<p>This section might seem challenging, but I suggest taking your time and coding along if possible. But, of course, you’ll probably be fine if you’re a more experienced engineer.</p>
<p>We will begin building our own island architecture implementation from the ground up. In more technical terms, we will implement a framework-independent partial hydration islands architecture implementation.</p>
<p>Phew! That’s a mouthfull.</p>
<p>Let’s break that down.</p>
<h3 id="heading-objectives">Objectives</h3>
<p>The goal of this exercise is not to build a full-blown library or to create an exact clone of the Astro Island implementation. No!</p>
<p>Our objective is to peel back the perceived layer of complexity and strip down component islands to a fundamental digestible unit.</p>
<p>Here are the functional requirements for our island implementation:</p>
<ol>
<li>Framework-independent: our solution must work across multiple frameworks, for example, <code>Preact</code>, <code>Vue</code>, <code>Petite-Vue</code>, and <code>React</code>.</li>
<li>A partial hydration islands architecture implementation: we will strip away JavaScript by default and only hydrate on an as-needed basis.</li>
<li>No frontend build step: for simplicity, our implementation will disregard a frontend build step, for example using <code>babel.</code></li>
<li>Support lazy hydration: this is a form of partial hydration where we can trigger hydration later and not immediately after loading the site. For example, if an island is off-screen (not in the viewport), we will not load the JavaScript for the island. We will only do so when the island is in view.</li>
</ol>
<h3 id="heading-installation">Installation</h3>
<p>Let’s call our island module <code>mini-island</code>.</p>
<p>To install <code>mini-island</code>, a developer will import our <em>soon-to-be-built</em> module as shown below:</p>
<pre><code class="lang-js">&lt;script type=<span class="hljs-string">"module"</span>&gt;
    {<span class="hljs-comment">/** import a mini-island.js module **/</span>}
    <span class="hljs-keyword">import</span> <span class="hljs-string">"/mini-island.js"</span>
&lt;/script&gt;
</code></pre>
<p>To enjoy the benefits of partial hydration, developers will add <code>mini-island.js</code> to their page with the promise of having a small JS footprint — a small price to pay to get partially hydrated islands of interactivity.</p>
<h3 id="heading-api-design">API design</h3>
<p>Our first objective is to make sure our solution is framework agnostic. An excellent native solution for framework-agnostic implementations is <strong>web components</strong>.</p>
<p>By definition, web components are a suite of technologies that allows us to create reusable custom elements.</p>
<p>If you’re new to web components, instead of rendering a standard HTML element, for example a <code>div</code>, we will create our custom HTML element, <code>mini-island</code>.</p>
<p><code>mini-island.js</code> will expose a custom element with the following basic usage:</p>
<pre><code class="lang-js">&lt;mini-island&gt;
 This is an island
&lt;/mini-island&gt;
</code></pre>
<p>Within <code>&lt;mini-island&gt;</code>, a developer will be able to leverage an island of interactivity on an otherwise static page.</p>
<p>We will support three different <code>&lt;mini-island&gt;</code> attributes to handle partial and lazy hydration: <code>client:idle</code>, <code>client:visible</code> and <code>client:media={QUERY}</code>.</p>
<p>Here’s an example of how they’d be used on <code>&lt;mini-island&gt;</code>:</p>
<pre><code class="lang-js">&lt;mini-island client:idle /&gt; 
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:visible</span> /&gt;</span></span> 
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:media</span>=<span class="hljs-string">"(max-width: 400px)"</span> /&gt;</span></span>
</code></pre>
<p>These attributes will affect how the island is hydrated.</p>
<ul>
<li><code>client:idle</code>: load and hydrate JavaScript when the whole page is loaded and the browser is idle.</li>
<li><code>client:visible</code>: we will load and hydrate the island JavaScript once the island is visible, for example, when it's entered the user’s viewport.</li>
<li><code>client:media</code>: we will load and hydrate the island once the query is satisfied, for example <code>client:media="(max-width: 400px)"</code>.</li>
</ul>
<p>There’s one final piece to our API design. How will developers define the scripts or markup to be hydrated?</p>
<p>We will use the <code>&lt;template&gt;</code> HTML element, the content template element.</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- ❌ incorrect usage: --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:idle</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"this should be partially hydrated"</span>)
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>

<span class="hljs-comment">&lt;!-- ✅ correct usage: --&gt;</span> 
<span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:idle</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- use the &lt;template&gt; element --&gt;</span>     
  <span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"this should be partially hydrated"</span>)
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
</code></pre>
<p><code>&lt;template&gt;</code> is generally used for holding <code>HTML</code> that shouldn’t be rendered immediately on page load. But the <code>HTML</code> may be instantiated via JavaScript.</p>
<p>For example, assuming a user wanted to log a warning to the console but wanted to use our island implementation, they’d do the following:</p>
<pre><code class="lang-js">&lt;mini-island&gt; 
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span> Warning, something may be wrong <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">data-island</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript"> 
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"something has gone wrong"</span>)
     </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span></span>
</code></pre>
<p>When the above is rendered, the <code>&lt;h2&gt; Warning, something may be wrong &lt;/h2&gt;</code> message will be displayed. But child elements of the <code>template</code> will not be rendered by default, that is the <code>script</code> will never be executed.</p>
<p>Our <code>mini-island</code> implementation will grab the content of the <code>template</code> and initialise the <code>&lt;script&gt;</code> when desired.</p>
<p>For example, if the user passes a <code>client:visible</code> attribute, we will ensure the script only runs when the island is visible.</p>
<pre><code class="lang-js">&lt;mini-island client:visible&gt; 
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span> Warning, something may be wrong <span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span></span>
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">data-island</span>&gt;</span>
     <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript"> 
        <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"something has gone wrong"</span>)
     </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span></span>
</code></pre>
<p>It’s important to note that we expect the developer to pass a <code>data-island</code> attribute to the <code>template</code>. We will only hydrate templates with the <code>data-island</code> attribute to avoid interfering with other potential user-defined templates.</p>
<p>Don’t worry if these seem fuzzy right now. We will implement and test these with examples that’ll solidify your understanding.</p>
<h3 id="heading-getting-started-1">Getting started</h3>
<p>Ready?</p>
<p>Start by creating a <code>mini-island.js</code> file in whatever directory you want.</p>
<p>In <code>mini-island</code>, create a barebones custom component as annotated below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>

<span class="hljs-comment">/**
 * Define a MiniIsland class to encapsulate the behaviour of 
our custom element, &lt;mini-island&gt;
 * This class extends HTMLElement where the HTMLElement 
interface represents any HTML element.
 */</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MiniIsland</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HTMLElement</span> </span>{
  <span class="hljs-comment">/**
   * Define the name for the custom element as a static class 
property.
   * Custom element names require a dash to be used in them 
(kebab-case).
   * The name can't be a single word. ✅ mini-island ❌ 
miniIsland
   */</span>
  <span class="hljs-keyword">static</span> tagName = <span class="hljs-string">'mini-island'</span>;
  <span class="hljs-comment">/**
   * Define the island element attributes
   *, e.g., &lt;mini-island data-island&gt;
   */</span>
  <span class="hljs-keyword">static</span> attributes = {
    <span class="hljs-attr">dataIsland</span>: <span class="hljs-string">"data-island"</span>,
  };
}

<span class="hljs-comment">/**
 * Our solution relies heavily on web components. Check that the
 * browser supports web components via the 'customElements' property
 */</span>

<span class="hljs-keyword">if</span> (<span class="hljs-string">'customElements'</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>) {
  <span class="hljs-comment">/**
   * Register our custom element on the CustomElementRegistry object using the define method.
   *
   * NB: The CustomElementRegistry interface provides methods for registering custom elements and querying registered elements.
   *
   * NB: The arguments to the define method are the name of the custom element (mini-island)
   * and the class (MiniIsland) that defines the behaviour of the custom element.
   *
   * NB: "MiniIsland.tagName" below represents the static class property, i.e., "static tagName".
   */</span>
  <span class="hljs-built_in">window</span>.customElements.define(MiniIsland.tagName, MiniIsland);
} <span class="hljs-keyword">else</span> {
  <span class="hljs-comment">/**
   * custom elements not supported, log an error to the console
   */</span>
  <span class="hljs-built_in">console</span>.error(
    <span class="hljs-string">'Island cannot be initiated because Window.customElements is unavailable.'</span>
  );
}
</code></pre>
<p>Let’s get some basic manual testing to nudge us in the right direction.</p>
<p>Create a new <code>demos/initial.html</code> file with the following content:</p>
<pre><code class="lang-js">&lt;!DOCTYPE html&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Initial island demo<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
      <span class="hljs-keyword">import</span> <span class="hljs-string">"../mini-island.js"</span>;
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Initial island demo<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>To view this via a local web server, run the following command from the project directory:</p>
<pre><code class="lang-bash"> npx local-web-server
</code></pre>
<p>By default, this should start a local static web server on port <code>8000</code>. We may now view the initial demo page on <code>http://localhost:8000/demos/initial.html</code></p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-14-at-07.29.14.png" alt="The initial demo page." width="721" height="257" loading="lazy">
<em>The initial demo page.</em></p>
<p>Let’s confirm that our custom element <code>mini-island</code> is registered rendering the custom element with a simple paragraph child element:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 demos/initial.html --&gt;</span> 
...
<span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Initial island demo<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span>
       <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello future island<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
</code></pre>
<p>This will render the custom element and the <code>Hello future island</code> paragraph as expected:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-14-at-07.27.26.png" alt="Rendering the custom element with a child element. " width="651" height="624" loading="lazy">
<em>Rendering the custom element with a child element.</em></p>
<p>Now, let’s go ahead and add some JavaScript within <code>&lt;mini-island&gt;</code> as shown below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 demos/initial.html --&gt;</span> 
...
<span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello future island<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
    <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"THIS IS A WARNING FROM AN ISLAND"</span>);
  </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
</code></pre>
<p>If you refresh the page and check the browser console, you should see the warning logged.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-14-at-07.32.44.png" alt="Console warning from the island." width="714" height="601" loading="lazy">
<em>Console warning from the island.</em></p>
<p>This means the script was fired almost immediately. Not our ideal solution.</p>
<p>While images and video account for over 70% of the bytes downloaded for the average website, byte per byte, JavaScript has a more significant negative impact on performance.</p>
<p>So, our goal is to ensure JavaScript doesn’t run by default. We will render any relevant markup in the island (HTML and CSS) but defer the loading of JavaScript.</p>
<h3 id="heading-how-to-leverage-the-content-template-element">How to leverage the content template element</h3>
<p><code>&lt;template&gt;</code> is a native HTML element that’s near perfect for our use case.</p>
<p>The contents within a <code>&lt;template&gt;</code> element are parsed for correctness by the browser but not rendered.</p>
<p>For example, let’s go ahead and wrap the script from the previous example in a <code>&lt;template&gt;</code> element as shown below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 demos/initial.html --&gt;</span> 
...
<span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello future island<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
      <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"THIS IS A WARNING FROM AN ISLAND"</span>);
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
</code></pre>
<p>If you refresh the page, you’ll notice that the <code>Hello future island</code> paragraph is rendered, but the <code>script</code> within <code>&lt;template&gt;</code> isn’t, that is no log to the console.</p>
<p>This is step one: isolate JavaScript from being loaded right away.</p>
<p>However, the eventual goal here is to ensure the developer can decide when to run the <code>script</code> within our island <code>template</code>.</p>
<p>As discussed in the proposed API implementation, consider the following:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:visible</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello future island<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
      <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"THIS IS A WARNING FROM AN ISLAND"</span>);
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
</code></pre>
<p>With the <code>client:visible</code> attribute, we will only initialise the script when the island is visible (within the user viewport).</p>
<p>Without taking the <code>client:</code> attributes into question, let’s go ahead and initialise any template content as soon as the <code>&lt;mini-island&gt;</code> element is attached to the DOM.</p>
<p>Consider the annotated code below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MiniIsland</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HTMLElement</span> </span>{
  <span class="hljs-comment">// ... </span>

  <span class="hljs-comment">/**
   * The connectedCallback is a part of the custom elements lifecycle callback.
   * It is invoked anytime the custom element is attached to the DOM
   */</span>
  <span class="hljs-keyword">async</span> connectedCallback() {
    <span class="hljs-comment">/**
     * As soon as the island is connected, we will go ahead and hydrate the island
     */</span>
    <span class="hljs-keyword">await</span> <span class="hljs-built_in">this</span>.hydrate();
  }

  hydrate() {
    <span class="hljs-comment">/**
     * Retrieve the relevant &lt;template&gt; child elements of the island
     */</span>
    <span class="hljs-keyword">const</span> relevantChildTemplates = <span class="hljs-built_in">this</span>.getTemplates();
  }
}
</code></pre>
<p>Now, we will turn our attention to <code>getTemplates()</code>.</p>
<p>Since <code>&lt;mini-island&gt;</code> is a custom element extending a standard <code>HTMLElement</code>, we can access traditional DOM querying methods such as <code>querySelectorAll</code>.</p>
<p>So, let’s use <code>querySelectorAll</code> to retrieve a list of all child template elements with a <code>data-island</code> attribute.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>
<span class="hljs-comment">// ...</span>

getTemplates() {
  <span class="hljs-comment">/**
   * querySelectorAll() returns a list of the document's elements that match the specified group of selectors.
   * The selector, in this case, is of the form "template[data-island]."
   *, i.e., this.querySelectorAll("template[data-island]")
  */</span>
  <span class="hljs-keyword">return</span> <span class="hljs-built_in">this</span>.querySelectorAll(
    <span class="hljs-string">`template[<span class="hljs-subst">${MiniIsland.attributes.dataIsland}</span>]`</span>
  );
}
</code></pre>
<p>Note that the <code>data-island</code> attribute is retrieved in the code above via <code>MiniIsland.attributes.dataIsland</code>.</p>
<p>Also, do you remember why we’re using the <code>data-island</code> attribute?</p>
<p>This is because we want to give developers the flexibility to use standard <code>&lt;template&gt;</code> elements within our island. So, our island will only concern itself with <code>&lt;template data-island&gt;</code> elements.</p>
<p>Now that we’ve retrieved the template node via <code>getTemplates()</code>, we will grab its content and hydrate it.</p>
<p>Let’s update the <code>hydrate</code> method as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>
<span class="hljs-comment">// ...</span>
hydrate() {
    <span class="hljs-comment">/**
     * Retrieve the relevant &lt;template&gt; child elements of the island
     */</span>
    <span class="hljs-keyword">const</span> relevantChildTemplates = <span class="hljs-built_in">this</span>.getTemplates();
    <span class="hljs-comment">/**
     * Grab the DOM subtree within the template and replace the template with live content
     */</span>
    <span class="hljs-built_in">this</span>.replaceTemplates(relevantChildTemplates);
}
</code></pre>
<p>The <code>replaceTemplates</code> method is as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>
<span class="hljs-comment">// ...</span>
 replaceTemplates(templates) {
    <span class="hljs-comment">/**
     * Iterate over all nodes in the template list.
     * templates refer to a NodeList of templates
     * node refers to a single &lt;template&gt;
     */</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> node <span class="hljs-keyword">of</span> templates) {
      <span class="hljs-comment">/**
       * replace the &lt;template&gt; with its HTML content
       * e.g., &lt;template&gt;&lt;p&gt;Hello&lt;/p&gt;&lt;/template&gt; becomes &lt;p&gt;Hello&lt;/p&gt;
       */</span>
      node.replaceWith(node.content);
    }
  }
</code></pre>
<p>Do you see what we’re doing here?</p>
<p>We’re grabbing the template DOM subtree, accessing its content and removing the <code>&lt;template&gt;</code> element.</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 👀 before --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span>

<span class="hljs-comment">&lt;!-- ✅ after --&gt;</span> 
<span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span>
</code></pre>
<p>This will attach the content to the DOM and kick off rendering and script loading.</p>
<p>With the templates now replaced, let’s go ahead and change the initial demo file to hold a more tangible example, as shown below:</p>
<pre><code class="lang-js">&lt;!-- 📂 demos/initial.html --&gt; 
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello future island<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">data-island</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
      <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"THIS IS A WARNING FROM AN ISLAND"</span>);
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span></span>
</code></pre>
<p>Note that the <code>&lt;template&gt;</code> element has the <code>data-island</code> attribute. This is how we signal to the island to hydrate the template content.</p>
<p>Now, refresh your browser and notice how the <code>console.warn</code> is triggered.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-15-at-07.10.42.png" alt="Hydrated island script. " width="704" height="632" loading="lazy">
<em>Hydrated island script.</em></p>
<p>If you also inspect the elements, you’ll notice that the <code>&lt;template&gt;</code> has been replaced with its live child content.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-15-at-07.11.54.png" alt="Replaced island <template> element." width="698" height="747" loading="lazy">
<em>Replaced island &lt;template&gt; element.</em></p>
<p>We’re officially hydrating our island!</p>
<h3 id="heading-how-to-handle-lazy-hydration-via-client-attributes">How to handle lazy hydration via “client:” attributes</h3>
<p>Our current solution isn’t going to win us any awards. As soon as the island is attached to the DOM, we hydrate the island. Let’s make it better by introducing lazy hydration.</p>
<p>Lazy hydration is a form of partial hydration where we hydration later — not immediately after page load.</p>
<p>Lazy hydration is powerful because we can determine what’s essential or priority for our site, that is we can choose to delay the execution of unimportant JavaScript.</p>
<p>Update the <code>initial.html</code> document to consider our first use case. Here’s the updated code:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 demos/initial.html --&gt;</span> 
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Initial island demo<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
      <span class="hljs-keyword">import</span> <span class="hljs-string">"../mini-island.js"</span>;
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Initial island demo<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- 👀 look here  --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span> <span class="hljs-attr">style</span>=<span class="hljs-string">"padding-bottom: 100vh"</span>&gt;</span>Scroll down<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- 👀 look here  --&gt;</span>     
    <span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:visible</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello island<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">data-island</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
          <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"THIS IS A WARNING FROM AN ISLAND"</span>);
        </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-15-at-07.18.38.png" alt="The client:visible demo" width="651" height="246" loading="lazy">
<em>The client:visible demo</em></p>
<p>We now have a paragraph that reads <code>scroll down</code>, which has a large enough bottom padding to push the island off the viewport.</p>
<p>With the <code>client:visible</code> attribute on the <code>&lt;mini-island&gt;</code>, we should not hydrate the island except when it’s visible, that is when the user scrolls to view the island.</p>
<p>However, test this in your browser.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-15-at-07.20.43.png" alt="The island is hydrated before being in view." width="696" height="591" loading="lazy">
<em>The island is hydrated before being in view.</em></p>
<p>The script is hydrated before we scroll (as soon as the page loads), and the <code>THIS IS A WARNING FROM AN ISLAND</code> message is logged.</p>
<p>Let’s prevent this from happening.</p>
<p>To achieve this, take a second look at the island hydrate method:</p>
<pre><code class="lang-js">  hydrate() {
    <span class="hljs-keyword">const</span> relevantChildTemplates = <span class="hljs-built_in">this</span>.getTemplates();
    <span class="hljs-built_in">this</span>.replaceTemplates(relevantChildTemplates);
  }
</code></pre>
<p>Conceptually, we aim to wait for specific loading conditions to be met before we replace the island templates. In this case, we want to wait until the island is visible.</p>
<p>In pseudo-code:</p>
<pre><code class="lang-js">  hydrate() {
     <span class="hljs-comment">// Get island conditions, e.g., client:visible, client:idle</span>
    <span class="hljs-comment">// If these exist, wait for the conditions to be met before the next steps</span>
    <span class="hljs-keyword">const</span> relevantChildTemplates = <span class="hljs-built_in">this</span>.getTemplates();
    <span class="hljs-built_in">this</span>.replaceTemplates(relevantChildTemplates);
  }
</code></pre>
<p>To manage our island loading conditions, let’s introduce a new <code>Conditions</code> class as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js </span>

<span class="hljs-comment">// ... </span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Conditions</span> </span>{

}

<span class="hljs-comment">// same existing code ...</span>
<span class="hljs-keyword">if</span> (<span class="hljs-string">"customElements"</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>) {
  <span class="hljs-built_in">window</span>.customElements.define(MiniIsland.tagName, MiniIsland);
} <span class="hljs-keyword">else</span> {
  <span class="hljs-built_in">console</span>.error(
    <span class="hljs-string">"Island cannot be initiated because Window.customElements is unavailable."</span>
  );
}
</code></pre>
<p>Within <code>Conditions</code>, we will introduce a static property that’s a key-value representation of the <code>client:</code> attribute and async methods.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/attr-promise.png" alt="An object with key-value corresponding to attribute and promise condition." width="2000" height="939" loading="lazy">
<em>An object with key-value corresponding to attribute and promise condition.</em></p>
<p>Our conditions will be fulfilled at a later unknown time. So, we will represent these with async functions. These async functions will return promises that are resolved when the associated condition is met.</p>
<p>Here’s the representation of this in code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// // 📂 mini-island.js</span>
<span class="hljs-comment">// ...</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Conditions</span> </span>{
  <span class="hljs-comment">/**
   * A map of loading conditions and their respective async methods
   */</span>
  <span class="hljs-keyword">static</span> map = {
    <span class="hljs-attr">idle</span>: Conditions.waitForIdle,
    <span class="hljs-attr">visible</span>: Conditions.waitForVisible,
    <span class="hljs-attr">media</span>: Conditions.waitForMedia,
  };

  <span class="hljs-keyword">static</span> waitForIdle() {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> resolve());
  }

  <span class="hljs-keyword">static</span> waitForVisible() {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> resolve());
  }

  <span class="hljs-keyword">static</span> waitForMedia() {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> resolve());
  }
}
</code></pre>
<p>At the moment, the promises resolve immediately. But let’s go ahead and flesh out our use case for <code>client:visible</code>.</p>
<p>First, we will expose a <code>getConditions</code> method on the <code>Conditions</code> class. The method will check if a certain DOM node (in our case, our <code>mini-island</code>) has an attribute in the form of <code>client:${condition}</code>.</p>
<p>Below’s the annotated implementation:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Conditions</span> </span>{
 <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">static</span> getConditions(node) {
    <span class="hljs-comment">/**
     * The result variable will hold the 
     * key:value representing condition:attribute.
     * e.g., For &lt;mini-island client:visible&gt;
     * result should be { visible: "" }
     * and for &lt;mini-island client:media="(max-width: 400px)" /&gt;
     * result should be { media: "(max-width: 400px)" }
     */</span>
    <span class="hljs-keyword">let</span> result = {};

    <span class="hljs-comment">/**
     * Loop over all keys of the static map, 
     *, i.e., ["idle", "visible", "media"]
     */</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> condition <span class="hljs-keyword">of</span> <span class="hljs-built_in">Object</span>.keys(Conditions.map)) {
      <span class="hljs-comment">/**
       * Check if the node has the attribute 
       * of the form "client:${key}".
       */</span>
      <span class="hljs-keyword">if</span> (node.hasAttribute(<span class="hljs-string">`client:<span class="hljs-subst">${condition}</span>`</span>)) {
        <span class="hljs-comment">/**
         * If the node has the attribute...
         * save the condition (key) - attribute (value)    
         * to the result object
         */</span>
        result[condition] = node.getAttribute(<span class="hljs-string">`client:<span class="hljs-subst">${condition}</span>`</span>);
      }
    }
    <span class="hljs-comment">/** return the result */</span>
    <span class="hljs-keyword">return</span> result 
  }
}
</code></pre>
<p>Next, we will expose a <code>hasConditions</code> method responsible for checking if an island has one or more conditions:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>
<span class="hljs-comment">// ...</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Conditions</span> </span>{
 <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">static</span> hasConditions(node) {
    <span class="hljs-comment">/**
     * Using the "getConditions" static class method, retrieve
     * a conditions attributes map
     */</span>
    <span class="hljs-keyword">const</span> conditionAttributesMap = Conditions.getConditions(node);

    <span class="hljs-comment">/**
     * Check the length of the result keys to determine if there are
     * any loading conditions on the node
     */</span>
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Object</span>.keys(conditionAttributesMap).length &gt; <span class="hljs-number">0</span>;
  }
}
</code></pre>
<p>With <code>hasConditions</code> and <code>getConditions</code> ready, let’s go ahead and use these within the <code>MiniIsland</code> hydrate method.</p>
<p>First, here’s the current state of the <code>hydrate</code> method.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MiniIsland</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HTMLElement</span> </span>{
 <span class="hljs-comment">// ...</span>
  hydrate() {
    <span class="hljs-keyword">const</span> relevantChildTemplates = <span class="hljs-built_in">this</span>.getTemplates();
    <span class="hljs-built_in">this</span>.replaceTemplates(relevantChildTemplates);
  }
 <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>Now, update the method with the following. I have provided annotations to make it easier to understand.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">MiniIsland</span> <span class="hljs-keyword">extends</span> <span class="hljs-title">HTMLElement</span> </span>{
 <span class="hljs-comment">// ...</span>
  <span class="hljs-keyword">async</span> hydrate() {
    <span class="hljs-comment">/**
     * conditions will hold an array of potential
     * promises to be resolved before hydration
     */</span>
    <span class="hljs-keyword">const</span> conditions = [];

    <span class="hljs-comment">/**
     * Get the condition - attribute value map
     * NB: the argument passed to 
     * `Conditions.getConditions` is the island node
     */</span>
    <span class="hljs-keyword">let</span> conditionAttributesMap = Conditions.getConditions(<span class="hljs-built_in">this</span>);

    <span class="hljs-comment">/**
     * Loop over the conditionAttributesMap variable
     */</span>
    <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> condition <span class="hljs-keyword">in</span> conditionAttributesMap) {
      <span class="hljs-comment">/**
       * Grab the condition async function from the static map
       * Remember that the function that returns a promise when invoked
       */</span>
      <span class="hljs-keyword">const</span> conditionFn = Conditions.map[condition];

      <span class="hljs-comment">/**
       * Check if the condition function exists
       */</span>
      <span class="hljs-keyword">if</span> (conditionFn) {
        <span class="hljs-comment">/**
         * Invoke the condition function with two arguments:
         * (1) The value of the condition attribute set on the node 
         * For example: 
         * for &lt;mini-island client:visible /&gt; this is an empty string ""
         * for &lt;mini-island client:media="(max-width: 400px)" /&gt;
         * This is the string "(max-width: 400px)"
         *
         * (2) The node, i.e., the island DOM node
         */</span>
        <span class="hljs-keyword">const</span> conditionPromise = conditionFn(
          conditionAttributesMap[condition],
          <span class="hljs-built_in">this</span>
        );

        <span class="hljs-comment">/**
         * append the promise to the conditions array
         */</span>

        conditions.push(conditionPromise);
      }

      <span class="hljs-comment">/**
       * Await all promise conditions to be 
       * resolved before replacing the template nodes
       */</span>
      <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all(conditions);
      <span class="hljs-comment">/**
       * Retrieve the relevant &lt;template&gt; child elements of the island
       */</span>
      <span class="hljs-keyword">const</span> relevantChildTemplates = <span class="hljs-built_in">this</span>.getTemplates();
      <span class="hljs-comment">/**
       * Grab the DOM subtree in the template
       * and replace the template with live content
       */</span>
      <span class="hljs-built_in">this</span>.replaceTemplates(relevantChildTemplates);
    }
  }
}
</code></pre>
<p>At the moment, remember that our condition promises in <code>Conditions</code> resolve immediately.</p>
<p>Before we test our solution, we must satisfy the condition for the <code>client:visible</code> attribute.</p>
<p>How do we ensure that the island is visible?</p>
<p>The best solution here is to use the <code>IntersectionObserver</code> API. Let’s take advantage of that as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>

<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Conditions</span> </span>{
 <span class="hljs-comment">// ...</span>
   <span class="hljs-comment">/**
   *
   * <span class="hljs-doctag">@param <span class="hljs-variable">noop</span></span> - the value of the condition attribute.
   * This is named "noop" as it is not relevant in this condition, i.e.,
   * as per our API, client:visible always has a falsy attribute value, e.g.,
   * ✅ &lt;mini-island client:visible /&gt;
   * ❌ &lt;mini-island client:visible={some-value} /&gt;
   * <span class="hljs-doctag">@param <span class="hljs-variable">el</span></span> - the node element.
   * This represents our island DOM node passed during hydration
   * <span class="hljs-doctag">@returns </span>- a Promise that resolves when "el" is visible
   * NB: relies on the Intersection Observer API
   */</span>
  <span class="hljs-keyword">static</span> waitForVisible(noop, el) {
    <span class="hljs-comment">/**
     * If the Intersection Observer API is not available,
     * go ahead and exit immediately.
     */</span>
    <span class="hljs-keyword">if</span> (!(<span class="hljs-string">"IntersectionObserver"</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>)) {
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-comment">/**
     * Otherwise, set up a new Promise that is resolved when the
     * node parameter (our island DOM node) is visible
     */</span>
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
      <span class="hljs-keyword">let</span> observer = <span class="hljs-keyword">new</span> IntersectionObserver(<span class="hljs-function">(<span class="hljs-params">entries</span>) =&gt;</span> {
        <span class="hljs-keyword">let</span> [entry] = entries;

        <span class="hljs-comment">/**
         * is it visible?
         */</span>
        <span class="hljs-keyword">if</span> (entry.isIntersecting) {
          <span class="hljs-comment">/**
           * remove observer
           */</span>
          observer.unobserve(entry.target);
          <span class="hljs-comment">/**
           * resolve promise
           */</span>
          resolve();
        }
      });

      <span class="hljs-comment">/**
       * set up the observer on the "el" argument
       */</span>
      observer.observe(el);
    });
  }
}
</code></pre>
<p>This is excellent work!</p>
<p>Return to the demo <code>initial.html</code> application running in your browser, refresh, and notice how the island behaves.</p>
<p>The island is no longer hydrated until we scroll down and the island is visible 🎉</p>
<p>Well done, mate! Give yourself a round of applause and a cuppa tea. We’ve smashed it. Take a pause if you need one, and let’s get on the next set of requirements when you’re ready.</p>
<h3 id="heading-how-to-support-the-clientidle-and-clientmedia-conditions">How to support the <code>client:idle</code> and <code>client:media</code> conditions</h3>
<p>We have a pretty robust solution within the <code>hydrate</code> method. So, to support more loading conditions, we have to flesh out the other condition promises.</p>
<h4 id="heading-waitforidle">waitForIdle</h4>
<p>Take a pause and consider how we should do this. For example, what heuristic do we rely on the determine when the browser is “idle”?</p>
<p>It begs the question, what’s “idle” in this case?</p>
<p>Well, for our implementation, the definition of idle is when the browser is not actively loading any resources, and no latency-critical events, such as animation and input responses, are in progress.</p>
<p>To achieve this, we will rely on two properties:</p>
<p>(i) The <code>document.readyState</code> event</p>
<p>If the value of this event is <code>complete</code>, the document and all sub-resources have finished loading. This includes all dependent resources such as stylesheets, scripts, iframes, and images.</p>
<p>Listening to this event ensures we hydrate the island when all other essential assets have been downloaded.</p>
<p>(ii) The <code>window.requestIdleCallback()</code> method</p>
<p>By definition, the <code>window.requestIdleCallback()</code> method will queue a function to be called when a browser is idle. This ensures the function is only executed when the browser handles no latency-critical event.</p>
<p>Let’s put these together and create a promise that resolves when the <code>document.readyState</code> event is <code>complete</code>, and no latency-critical events are being handled.</p>
<p>Here’s the implementation below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>
<span class="hljs-comment">// ...</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Conditions</span> </span>{
 <span class="hljs-comment">// ...</span>
 <span class="hljs-keyword">static</span> waitForIdle() {
    <span class="hljs-keyword">const</span> onLoad = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
      <span class="hljs-comment">/**
       * The document.readyState property 
       * describes the loading state of the document.
       */</span>
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">document</span>.readyState !== <span class="hljs-string">"complete"</span>) {
        <span class="hljs-comment">/**
         * Set up an event listener for the "load" event.
         * The load event is fired when the whole page 
         * has loaded, including all dependent resources
         * such as stylesheets, scripts, iframes, and
         * images.
         */</span>
        <span class="hljs-built_in">window</span>.addEventListener(
          <span class="hljs-string">"load"</span>,
          <span class="hljs-function">() =&gt;</span> {
            <span class="hljs-comment">/**
             * resolve this promise once the "load" event is fired.
             */</span>
            resolve();
          },
          <span class="hljs-comment">/**
           * Remove the listener after the first 
           * invocation of the "load" event.
           */</span>
          { <span class="hljs-attr">once</span>: <span class="hljs-literal">true</span> }
        );
      } <span class="hljs-keyword">else</span> {
        resolve();
      }
    });

    <span class="hljs-comment">/**
     * The window.requestIdleCallback() method queues a  
     * function to be called during a browser's idle periods. 
     * This enables developers to perform background 
     * and low-priority work on the main event loop
     */</span>

    <span class="hljs-keyword">const</span> onIdle = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
      <span class="hljs-comment">/**
       * Check for "requestIdleCallback" support
       */</span>
      <span class="hljs-keyword">if</span> (<span class="hljs-string">"requestIdleCallback"</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>) {
        requestIdleCallback(<span class="hljs-function">() =&gt;</span> {
          <span class="hljs-comment">/**
           * pass the promise resolve function 
           * as the operation to be queued
           */</span>
          resolve();
        });
      } <span class="hljs-keyword">else</span> {
        <span class="hljs-comment">/**
         * resolve the promise immediately
         * if requestIdleCallback isn't supported
         */</span>
        resolve();
      }
    });

    <span class="hljs-comment">/**
     * waitForIdle will wait for both 
     * promises to be resolved, i.e., onIdle and onLoad
     */</span>
    <span class="hljs-keyword">return</span> <span class="hljs-built_in">Promise</span>.all([onIdle, onLoad]);
  }
}
</code></pre>
<p>Now, go to the <code>initial.html</code> demo file and update the file as shown below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 demos/initial.html --&gt;</span> 
<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- ... --&gt;</span>
  <span class="hljs-comment">&lt;!-- content unchanged --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Initial island demo<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
      <span class="hljs-attr">src</span>=<span class="hljs-string">"https://raw.githubusercontent.com/ohansemmanuel/larder/main/large_image.jpeg"</span>
      <span class="hljs-attr">alt</span>=<span class="hljs-string">"34MB large satellite image from Effigis."</span>
    /&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:idle</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello island<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">data-island</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
          <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"THIS IS A WARNING FROM AN ISLAND"</span>);
        </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Note that we’ve introduced a large <code>34MB</code> image from <a target="_blank" href="https://effigis.com/en/solutions/satellite-images/satellite-image-samples/">Effigis</a> and passed a <code>client:idle</code> attribute to <code>&lt;mini-island&gt;</code>.</p>
<p>Tip: consider downloading the large image and referencing it locally instead of hitting the GitHub servers repeatedly.</p>
<p>The large image will keep the browser busy for some time. Before testing this in the browser, I suggest disabling the browser cache via developer tools.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-15-at-11.43.31.png" alt="The disable cache property in Firefox." width="699" height="264" loading="lazy">
<em>The disable cache property in Firefox.</em></p>
<p>Open the page in the browser and notice how the script is not invoked until the browser has finished loading the large image and is in an idle state.</p>
<p>This is great!</p>
<p>Instead of potentially allowing non-priority JavaScript code to compete for the browser resources, we’ve shelved that to be initialised later during the browser’s idle period.</p>
<h4 id="heading-waitformedia">waitForMedia</h4>
<p>The media condition is fascinating. The island is only hydrated when a CSS media query is met. This is useful for mobile toggles or other elements only visible on specific screen sizes.</p>
<p>We will leverage the <code>window.matchMedia()</code> to determine if the document matches the media query string.</p>
<p>Here’s the annotated implementation:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 mini-island.js</span>
<span class="hljs-comment">// ...</span>
<span class="hljs-class"><span class="hljs-keyword">class</span> <span class="hljs-title">Conditions</span> </span>{
<span class="hljs-comment">/**
   *
   * <span class="hljs-doctag">@param <span class="hljs-type">{*}</span> <span class="hljs-variable">query</span></span> - the query string 
   * passed to the client:media attribute
   * <span class="hljs-doctag">@returns </span>Promise that resolves when
   * the document matches the passed CSS media query
   */</span>
  <span class="hljs-keyword">static</span> waitForMedia(query) {
    <span class="hljs-comment">/**
     * window.matchMedia(query) returns A MediaQueryList object.
     * This object stores information on a media query
     * applied to a document and one of the properties 
     * on this object is "matches" - a boolean for
     * whether the document matches the media query or not.
     * Create a new simple object of similar form, i.e.,  
     * with a "matches" property
     */</span>
    <span class="hljs-keyword">let</span> queryList = {
      <span class="hljs-attr">matches</span>: <span class="hljs-literal">true</span>,
    };

    <span class="hljs-keyword">if</span> (query &amp;&amp; <span class="hljs-string">"matchMedia"</span> <span class="hljs-keyword">in</span> <span class="hljs-built_in">window</span>) {
     <span class="hljs-comment">/** 
       Override our stub with the actual query list
     */</span>
      queryList = <span class="hljs-built_in">window</span>.matchMedia(query);
    }

    <span class="hljs-comment">/**
     * If matchMedia isn't supported or the 
     * query is truthy, return immediately
     * e.g., truthy if matchMedia isn't in the window object
     */</span>
    <span class="hljs-keyword">if</span> (queryList.matches) {
      <span class="hljs-keyword">return</span>;
    }

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
      <span class="hljs-comment">/**
       * Set a new listener on the queryList object
       * and resolve the promise when there's a match
       */</span>
      queryList.addListener(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (e.matches) {
          resolve();
        }
      });
    });
  }
}
</code></pre>
<p>With this in place, we may update the <code>initial.html</code> demo file to the following:</p>
<pre><code class="lang-html"><span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-comment">&lt;!-- content remains the same --&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Initial island demo<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:media</span>=<span class="hljs-string">"(max-width: 400px)"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>Hello island<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">data-island</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
          <span class="hljs-built_in">console</span>.warn(<span class="hljs-string">"THIS IS A WARNING FROM AN ISLAND"</span>);
        </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Now refresh the page in your browser and notice how the script is never initialised until you resize your browser window to match the CSS query, that is a maximum width of <code>400px</code>.</p>
<h3 id="heading-how-to-support-frameworks-vue-petite-vue-and-preact">How to support frameworks: Vue, Petite-vue, and Preact</h3>
<p>Our <code>&lt;mini-island&gt;</code> implementation is simple yet effective. But you may not appreciate it until you’ve seen it used with other frameworks. Coincidentally, this is also a part of our objectives – to develop a framework-agnostic solution.</p>
<p>The following sections show framework examples utilising <code>&lt;mini-island&gt;</code>. To do this, we will build out the same framework user interface in the form of a simple counter.</p>
<h4 id="heading-vue">Vue</h4>
<p>Vue is a JavaScript framework for building user interfaces. Vue’s mental model builds on top of standard HTML, CSS, and JavaScript, making it easy to understand for most people.</p>
<p>As expected of a modern UI framework, Vue is declarative and reactive.</p>
<p>Let’s go ahead and build a counter application leveraging Vue and <code>&lt;mini-island&gt;</code> as shown below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 demos/vue.html --&gt;</span>

<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Vue mini-island demo<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
      <span class="hljs-keyword">import</span> <span class="hljs-string">"../mini-island.js"</span>;
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Vue<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">mark</span>&gt;</span>This is a vue counter <span class="hljs-tag">&lt;/<span class="hljs-name">mark</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      By default, this button does not load any Javascript and isn't hydrated.
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      Resize your browser to match the media query:
      <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>(max-width: 400px)<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> to hydrate the island
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:media</span>=<span class="hljs-string">"(max-width: 400px)"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"vue-app"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"count++"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>⬆️<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Vue<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">v-html</span>=<span class="hljs-string">"count"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>clicks<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">data-island</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
          <span class="hljs-keyword">import</span> { createApp } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://unpkg.com/vue@3.2.36/dist/vue.esm-browser.prod.js"</span>;

          createApp({
            <span class="hljs-attr">data</span>: <span class="hljs-function">() =&gt;</span> ({ <span class="hljs-attr">count</span>: <span class="hljs-number">0</span> }),
          }).mount(<span class="hljs-string">"#vue-app"</span>);
        </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>It’s okay if you do not understand the Vue code snippets. What’s important is the following:</p>
<ul>
<li>The HTML markup is rendered as soon as the HTML page is loaded and parsed.</li>
<li>This includes the static counter markup within <code>mini-island</code>, that is:<br>      <code>&lt;div id="vue-app"&gt;</code><br>        <code>&lt;button @click="count++"&gt;</code><br>          <code>&lt;span&gt;⬆️&lt;/span&gt;</code><br>      <code>` </code><div><code>`&lt;strong&gt;Vue&lt;/strong&gt;</code><br>            <code>&lt;div&gt;</code><br>              <code>&lt;span v-html="count"&gt;0&lt;/span&gt;</code><br>              <code>&lt;span&gt;-&lt;/span&gt;</code><br>              <code>&lt;span&gt;clicks&lt;/span&gt;</code><br>            <code>&lt;/div&gt;</code><br>          <code>&lt;/div&gt;</code><br>        <code>&lt;/button&gt;</code><br>      <code>&lt;/div&gt;</code></div></li>
<li>But the counter is not hydrated at this point. So, clicking the counter will not increase the count. This is because Vue hasn’t been loaded, and the counter button is not yet hydrated.</li>
<li>Consider the loading condition set on the island, that is <code>client:media="(max-width: 400px)"</code>.</li>
<li>Now, resize your browser (take advantage of the developer tools) to a width less than <code>400px</code> to hydrate the island.</li>
<li>This will import Vue and hydrate the counter. Here’s the code responsible for within the island <code>template</code>:<br>      <code>&lt;template data-island&gt;</code><br>          <code>&lt;script type="module"&gt;</code><br>                <code>import { createApp } from "https://unpkg.com/vue@3.2.36/dist/vue.esm-browser.prod.js";</code><br>      <code>` </code>createApp({<code>`data: () =&gt; ({ count: 0 }),</code><br>            <code>}).mount("#vue-app");</code><br>          <code>&lt;/script&gt;</code><br>      <code>&lt;/template&gt;</code></li>
<li>The counter should now be hydrated. We may now click to our heart’s content.</li>
</ul>
<h4 id="heading-petite-vue">Petite-vue</h4>
<p>From the official Vue <a target="_blank" href="https://vuejs.org/guide/extras/ways-of-using-vue.html#standalone-script">documentation</a>, Vue also provides an alternative distribution called petite-vue that is optimised for progressively enhancing existing HTML.</p>
<p>This is perfect for our use case.</p>
<p>Let’s go ahead and create a similar demo using <code>petite-vue</code> as shown below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 demos/petite-vue.html --&gt;</span>

<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Vue mini-island demo<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
      <span class="hljs-keyword">import</span> <span class="hljs-string">"../mini-island.js"</span>;
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Petite-vue<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">mark</span>&gt;</span>This is a petite-vue counter <span class="hljs-tag">&lt;/<span class="hljs-name">mark</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      By default, this button does not load any Javascript and isn't hydrated.
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>
      Resize your browser to match the media query:
      <span class="hljs-tag">&lt;<span class="hljs-name">code</span>&gt;</span>(max-width: 400px)<span class="hljs-tag">&lt;/<span class="hljs-name">code</span>&gt;</span> to hydrate the island
    <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:media</span>=<span class="hljs-string">"(max-width: 400px)"</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"vue-app"</span> <span class="hljs-attr">v-scope</span>=<span class="hljs-string">"{ count: 0 }"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">button</span> @<span class="hljs-attr">click</span>=<span class="hljs-string">"count++"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>⬆️<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>

          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Petite-vue<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
            <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span> <span class="hljs-attr">v-html</span>=<span class="hljs-string">"count"</span>&gt;</span>0<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>clicks<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">data-island</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
          <span class="hljs-keyword">import</span> { createApp } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://unpkg.com/petite-vue@0.4.1/dist/petite-vue.es.js"</span>;

          createApp().mount(<span class="hljs-string">"#vue-app"</span>);
        </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>Apart from a few changes, the code above is identical to the standard Vue API.</p>
<p>Here’s how this works:</p>
<ul>
<li>The HTML markup is rendered as soon as the HTML page is loaded and parsed.</li>
<li>This includes the static counter markup within <code>mini-island</code>, that is:<br>       <code>&lt;div id="vue-app" v-scope="{ count: 0 }"&gt;</code><br>              <code>&lt;button @click="count++"&gt;</code><br>                <code>&lt;span&gt;⬆️&lt;/span&gt;</code><br>      <code>` </code><div><code>`&lt;strong&gt;Vue&lt;/strong&gt;</code><br>                  <code>&lt;div&gt;</code><br>                    <code>&lt;span v-html="count"&gt;0&lt;/span&gt;</code><br>                    <code>&lt;span&gt;-&lt;/span&gt;</code><br>                    <code>&lt;span&gt;clicks&lt;/span&gt;</code><br>                  <code>&lt;/div&gt;</code><br>                <code>&lt;/div&gt;</code><br>              <code>&lt;/button&gt;</code><br>            <code>&lt;/div&gt;</code></div></li>
<li>NB: the significant difference in the code above is the introduction of the <code>v-scope</code> attribute to hold our count data variable.</li>
<li>The counter, however, is not hydrated at this point. So, clicking the counter will not increase the count. This is because petite-vue hasn’t been loaded, and the counter button is not yet hydrated.</li>
<li>Consider the loading condition set on the island, that is <code>client:media="(max-width: 400px)"</code></li>
<li>Now, resize your browser (use the developer tools) to a width less than <code>400px</code> to hydrate the island.</li>
<li>This will import Petite-vue and hydrate the counter. Here’s the code responsible for within the island <code>template</code>:<br>      <code>&lt;template data-island&gt;</code><br>        <code>&lt;script type="module"&gt;</code><br>          <code>import { createApp } from "https://unpkg.com/petite-vue@0.4.1/dist/petite-vue.es.js";</code><br>      <code>` </code>createApp().mount("#vue-app");<code>`&lt;/script&gt;</code><br>      <code>&lt;/template&gt;</code></li>
<li>The counter should now be hydrated. We may now click to our heart’s content.</li>
</ul>
<h4 id="heading-preact">Preact</h4>
<p>Preact is a fast 3kB alternative to React with the same modern API, and it can be used in the browser without any transpiration steps.</p>
<p>Let’s go ahead and create a similar demo using Preact, as shown below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 demos/preact.html --&gt;</span>

<span class="hljs-meta">&lt;!DOCTYPE <span class="hljs-meta-keyword">html</span>&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"UTF-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">http-equiv</span>=<span class="hljs-string">"X-UA-Compatible"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"IE=edge"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width, initial-scale=1.0"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Preact mini-island demo<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
      <span class="hljs-keyword">import</span> <span class="hljs-string">"../mini-island.js"</span>;
    </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Preact<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is a preact counter<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>By default, this button is not rendered or hydrated<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">mini-island</span> <span class="hljs-attr">client:idle</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"preact-app"</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">mark</span>
          &gt;</span>The counter island will be rendered and hydrated just above this mark
          when the browser is idle<span class="hljs-tag">&lt;/<span class="hljs-name">mark</span>
        &gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">template</span> <span class="hljs-attr">data-island</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"module"</span>&gt;</span><span class="javascript">
          <span class="hljs-keyword">import</span> { h, Component, render } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://esm.sh/preact"</span>;
          <span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"https://esm.sh/preact/hooks"</span>;
          <span class="hljs-keyword">import</span> htm <span class="hljs-keyword">from</span> <span class="hljs-string">"https://esm.sh/htm"</span>;

          <span class="hljs-comment">// Initialize htm with Preact</span>
          <span class="hljs-keyword">const</span> html = htm.bind(h);

          <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">App</span>(<span class="hljs-params">props</span>) </span>{
            <span class="hljs-keyword">const</span> [count, setCount] = useState(<span class="hljs-number">0</span>);

            <span class="hljs-keyword">const</span> increment = <span class="hljs-function">() =&gt;</span>
              setCount(<span class="hljs-function">(<span class="hljs-params">currentCount</span>) =&gt;</span> currentCount + <span class="hljs-number">1</span>);

            <span class="hljs-keyword">return</span> html`<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;<span class="hljs-name">button</span> <span class="hljs-attr">onClick</span>=</span></span><span class="hljs-subst">${() =&gt; increment()}</span><span class="xml"><span class="hljs-tag">&gt;</span>
                <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>⬆️ <span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>

                <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">strong</span>&gt;</span>Preact<span class="hljs-tag">&lt;/<span class="hljs-name">strong</span>&gt;</span>
                  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span></span><span class="hljs-subst">${count}</span><span class="xml"><span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>-<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                    <span class="hljs-tag">&lt;<span class="hljs-name">span</span>&gt;</span>clicks<span class="hljs-tag">&lt;/<span class="hljs-name">span</span>&gt;</span>
                  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
                <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
              <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
            <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>`</span>;
          }

          render(html`<span class="xml"><span class="hljs-tag">&lt;</span></span><span class="hljs-subst">${App}</span><span class="xml"><span class="hljs-tag"> /&gt;</span>`</span>, <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"preact-app"</span>));
        </span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">mini-island</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">ul</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>The document must be completely loaded<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span>The large image below must complete loading<span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">img</span>
      <span class="hljs-attr">src</span>=<span class="hljs-string">"https://raw.githubusercontent.com/ohansemmanuel/larder/main/large_image.jpeg"</span>
      <span class="hljs-attr">alt</span>=<span class="hljs-string">"34MB large satellite image from Effigis."</span>
    /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span>
</code></pre>
<p>The code above behaves differently from the previous framework examples.</p>
<p>Here’s how this works:</p>
<ul>
<li>The HTML markup is rendered after loading and parsing the HTML.</li>
<li>The counter, however, is not rendered or hydrated. This is because <code>mini-island</code> has a <code>client: idle</code> loading condition.</li>
<li>The counter will be rendered and hydrated when the browser is idle. For this to be the case, the large image in the document must complete loading.</li>
<li>Once this is loaded (including other associated document resources), Preact renders and hydrates the counter when the browser is idle.</li>
<li>The counter should now be hydrated; we may now click to our heart’s content.</li>
</ul>
<h2 id="heading-wrapping-up-this-chapter-2">Wrapping Up This Chapter</h2>
<p>When it comes to performance and deciding what rendering solution works for your application, no single solution fits all applications. </p>
<p>Depending on the application, we always have to make tradeoffs. But the island architecture provides very performant client applications without sacrificing rich interactivity.</p>
<p>The main goal of this chapter was to peel back the perceived layer of complexity and strip down component islands to a fundamental digestible unit with <code>&lt;mini-island&gt;</code>.</p>
<p>Now, we will take this knowledge into exploring component islands in Astro, and (almost) nothing will surprise you. That’s the definition of proper understanding.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-136.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chapter four.</em></p>
<h1 id="heading-chapter-4-the-secret-life-of-astro-component-islands-1">Chapter 4: The Secret Life of Astro Component Islands</h1>
<p>Component islands are the secret to Astro’s super-fast narrative. It’s time to learn everything about them.</p>
<h2 id="heading-what-youll-learn-3">What You’ll Learn</h2>
<ul>
<li>Hands-on experience working with framework components in Astro.</li>
<li>Responsible hydration and why it matters.</li>
<li>How component islands work in Astro.</li>
<li>Why islands are essential.</li>
</ul>
<h2 id="heading-how-islands-work-in-astro">How Islands Work in Astro</h2>
<p>Assume we’ve got an Astro application with static content: a navigation bar, some main content, a footer, and a side pane.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/a-6.png" alt="A static astro page structure" width="2000" height="1309" loading="lazy">
<em>A static astro page structure</em></p>
<p>If we need to introduce some interactivity content in the side pane of the application, how could we achieve this?</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/b-1.png" alt="Adding interactive content to the static page" width="2000" height="1309" loading="lazy">
<em>Adding interactive content to the static page</em></p>
<p>Astro provides the following ways to do this:</p>
<ul>
<li>We've seen how this works: introduce a <code>&lt;script&gt;</code> element to handle interactivity within your Astro component.</li>
<li>Use a supported framework component, and leverage a component island.</li>
</ul>
<p>The second option is the focus of this chapter.</p>
<p>At the time of writing, Astro lets you use components built with <code>React</code>, <code>Preact</code>, <code>Svelte</code>, <code>Vue</code>, <code>SolidJS</code>, <code>AlpineJS</code> or <code>Lit</code> in your Astro components. Moving on, I’ll refer to these as <strong>framework components</strong>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/framework-components.png" alt="Leveraging framework components in Astro." width="2000" height="2085" loading="lazy">
<em>Leveraging framework components in Astro.</em></p>
<p>So, why would we use framework components and not just provide native support via a <code>&lt;script&gt;</code> element?</p>
<p>It would be best to stick with a <code>&lt;script&gt;</code> element in cases where you can get by with vanilla JavaScript or TypeScript. But there are cases where we may favour a framework component. For example:</p>
<ul>
<li><strong>Design systems</strong>: using a pre-existing design system in an Astro project can save time, depending on the use case. It also helps keep all your applications looking and feeling the same way.</li>
<li><strong>Open-source</strong>: we might consider utilising a feature-rich open-source framework component already existing instead of building some highly interactive component from scratch. This way, we can easily use an open-source framework component in Astro.</li>
<li><strong>Ease of development</strong>: we may find building richer stateful user interfaces easier, more manageable, and faster to implement via framework components than vanilla JavaScript / TypeScript provided in <code>&lt;script&gt;</code>.</li>
</ul>
<p>To use a framework component in Astro, we leverage component islands.</p>
<p>Let’s return to our example application.</p>
<p>Assuming we’ve weighed the pros and cons and decided to introduce a framework component, the following section highlights the steps to take.</p>
<h3 id="heading-step-1-build-an-astro-site">Step 1: Build an Astro site</h3>
<p>We can’t use framework components without having some Astro site to use them in.</p>
<p>We’ve already seen how to build static sites with Astro, so creating a new static project is unnecessary. Instead, let’s start a new Astro with a project I’ve prepared.</p>
<p>Clone the project:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/understanding-astro/astro-islands-visual-example.git
</code></pre>
<p>Then, install dependencies and start the application via the following:</p>
<pre><code class="lang-bash">npm install 
npm run start
</code></pre>
<p>This will run the project in one of your local ports.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-03-11-at-14.06.52@2x.png" alt="The astro islands visual example project " width="2000" height="1125" loading="lazy">
<em>The astro islands visual example project</em></p>
<p>The project takes the same form as our hypothetical example — it’s got a navigation, main content, footer, and side pane.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/a-1-1.png" alt="A static astro page structure" width="2000" height="1309" loading="lazy">
<em>A static astro page structure</em></p>
<p>Within the side pane, there’s a <code>slot</code> to render our interactive content via a framework component.</p>
<p>In <code>src/pages/index.astro</code>, you’ll find the code responsible for rendering the page as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">import</span> DefaultIslandLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/DefaultIslandLayout.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DefaultIslandLayout</span> /&gt;</span></span>
</code></pre>
<p><code>DefaultIslandLayout</code> provides the layout for the entire page and includes a <code>slot</code> for rendering whatever children elements are passed to it. Initialise the project locally and take a look.</p>
<h3 id="heading-step-2-install-the-framework-integration">Step 2: Install the framework integration</h3>
<p>Astro provides official integrations for the supported framework components. In this example, we’ll use the <code>react</code> framework.</p>
<p>It’s important to note that the steps described here are the same regardless of the framework component of your choosing. Therefore, I’m sticking to <code>react</code> as many more developers arguably use it.</p>
<p>The most convenient way to add your framework integration is to use the <code>astro add</code> command, for example to add <code>react</code>, run the following commands:</p>
<pre><code class="lang-bash"><span class="hljs-comment"># using NPM</span>
npx astro add react
<span class="hljs-comment"># Using Yarn</span>
yarn astro add react
<span class="hljs-comment"># Using PNPM</span>
pnpm astro add react
</code></pre>
<p>This will automatically add the relevant framework dependencies to our project.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-03-11-at-14.56.20@2x.png" alt="Running astro add react." width="2440" height="984" loading="lazy">
<em>Running astro add react.</em></p>
<p>The command will also automatically update our project configuration, <code>astro.config.mjs</code>, to include the framework integration.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-03-11-at-14.57.00@2x.png" alt="Updating the project config file." width="2134" height="1090" loading="lazy">
<em>Updating the project config file.</em></p>
<p>Essentially, this breaks down the installation of a framework into our Astro project into two distinct processes:</p>
<ol>
<li>Install the framework dependencies.</li>
<li>Add the relevant framework integration in the project config file.</li>
</ol>
<p>If we didn’t use the <code>Astro add</code> command, we could achieve the same results manually by installing the framework dependencies and adding the framework integration in our project configuration file.</p>
<h3 id="heading-step-3-write-the-component-framework">Step 3: Write the component framework</h3>
<p>Our framework component will be a glorified counter. Assuming the page consists of an article a reader can upvote, we’ll build an upvote button.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/upvote-counter.png" alt="The upvote counter illustrated." width="2000" height="820" loading="lazy">
<em>The upvote counter illustrated.</em></p>
<p>Here’s the annotated <code>UpvoteContent</code> React component:</p>
<pre><code class="lang-js">&lt;!-- 📂 src/components/UpvoteContent.tsx --&gt;

<span class="hljs-keyword">import</span> { useState } <span class="hljs-keyword">from</span> <span class="hljs-string">"react"</span>;

<span class="hljs-comment">// The maximum number of upvotes available </span>
<span class="hljs-keyword">const</span> MAX_COUNT = <span class="hljs-number">50</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> UpvoteContent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// the initial state of the upvote counter </span>
  <span class="hljs-keyword">const</span> [upvoteCount, setUpvoteCount] = useState(<span class="hljs-number">0</span>);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
       // <span class="hljs-attr">update</span> <span class="hljs-attr">state</span> <span class="hljs-attr">when</span> <span class="hljs-attr">a</span> <span class="hljs-attr">user</span> <span class="hljs-attr">clicks</span> <span class="hljs-attr">the</span> <span class="hljs-attr">counter.</span> <span class="hljs-attr">check</span> <span class="hljs-attr">if</span>
       //<span class="hljs-attr">The</span> <span class="hljs-attr">maximum</span> <span class="hljs-attr">count</span> <span class="hljs-attr">value</span> <span class="hljs-attr">was</span> <span class="hljs-attr">reached</span> <span class="hljs-attr">first.</span> 
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> {
          setUpvoteCount((prevCount) =&gt;
            prevCount <span class="hljs-tag">&lt; <span class="hljs-attr">MAX_COUNT</span> ? <span class="hljs-attr">prevCount</span> + <span class="hljs-attr">1</span> <span class="hljs-attr">:</span> <span class="hljs-attr">prevCount</span>
          );
        }}
      &gt;</span>
       { /** Upvote counter SVG icon. shortened for brevity **/}
        <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> /&gt;</span>
        Upvote
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{`${upvoteCount} upvotes`}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

        {/** show a growing visual bar based on the upvote count **/}
        <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
          <span class="hljs-attr">style</span>=<span class="hljs-string">{{</span>
            <span class="hljs-attr">width:</span> `${<span class="hljs-attr">upvoteCount</span>}%`,
          }}
        /&gt;</span>

        {/** show a warning if the maximum count has been reached**/}
        {upvoteCount === MAX_COUNT &amp;&amp; (
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
            Max upvote reached
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        )}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>Don’t worry if you don’t understand <code>react</code>. The goal here is to know how to work with framework components in Astro. We could build the same component using any other framework we choose, like Vue or Svelte.</p>
<h3 id="heading-step-4-render-the-component-framework">Step 4: Render the component framework</h3>
<p>Let’s go ahead and render the framework component as shown below:</p>
<pre><code class="lang-js">&lt;!-- 📂 src/pages/none.astro --&gt;
---
<span class="hljs-keyword">import</span> { UpvoteContent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/UpvoteContent.jsx"</span>;
<span class="hljs-keyword">import</span> DefaultIslandLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/DefaultIslandLayout.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DefaultIslandLayout</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">DefaultIslandLayout</span>&gt;</span></span>
</code></pre>
<ul>
<li>Create a new page in <code>src/pages/none.astro</code></li>
<li>Render the <code>UpvoteContent</code> component as a child of <code>DefaultIslandLayout</code>, that is:<br>      <code>&lt;DefaultIslandLayout&gt;</code><br>        <code>&lt;UpvoteContent /&gt;</code><br>      <code>&lt;/DefaultIslandLayout&gt;</code></li>
<li><code>DefaultIslandLayout</code> takes the <code>UpvoteContent</code> child component and renders it within its layout slot.</li>
</ul>
<p>Now, open the <code>/none</code> page in the browser, and we should have the rendered <code>UpvoteContent</code> component rendered.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-03-13-at-12.59.52@2x.png" alt="Rendering the framework component." width="2000" height="1186" loading="lazy">
<em>Rendering the framework component.</em></p>
<p>The upvote counter is successfully rendered, but clicking the button doesn’t increase the count!</p>
<p>What’s going on? 🥹</p>
<h4 id="heading-its-not-a-bug-its-a-feature">It’s not a bug. It’s a feature.</h4>
<p>By default, when you render a framework component, Astro automatically renders it to HTML ahead of time, that is Astro strips out all of the component JavaScript.</p>
<p>Essentially, you get no interactivity from framework components by default.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/no-js-by-default.png" alt="If Astro launched a Twitter campaign, #NoJavscriptByDefault would make an excellent hashtag." width="2000" height="732" loading="lazy">
<em>If Astro launched a Twitter campaign, #NoJavscriptByDefault would make an excellent hashtag.</em></p>
<p>As it stands, what we currently have is technically not an island. We have the component markup rendered with no interactivity.</p>
<h2 id="heading-responsible-hydration">Responsible Hydration</h2>
<p>Astro helps you minimise JavaScript bloat when using framework components by leveraging responsible hydration.</p>
<p>If Astro renders your framework component to <code>100%</code> HTML, how do you hydrate (make interactive) the framework component?</p>
<p>In the context of Astro development, responsible hydration refers to Astro making no decision on when to hydrate your framework component and leaving that decision entirely up to the developer.</p>
<p>This is powerful but comes with the burden of decision resting on us — developers.</p>
<p>When technical decisions such as this need to be made, they must be made against specific requirements. In this case, the decision lies in evaluating two criteria, namely <strong>priority</strong> and <strong>interactivity</strong>.</p>
<ul>
<li>Priority: is this a high or low-priority user interface element?</li>
<li>Interactivity: should this element be interactive as soon as possible?</li>
</ul>
<p>We may represent this on a 2d plane as follows:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/hydration-plane.png" alt="Representing priority and interactivity on a 2d plane." width="1863" height="1601" loading="lazy">
<em>Representing priority and interactivity on a 2d plane.</em></p>
<p>There are four attributes you can pass to your rendered framework component, for example:</p>
<pre><code class="lang-js">&lt;ReactComponent attribute /&gt;
</code></pre>
<p>These attributes are called client directives (or, more generically, template directives). Here are the five client directives that control the hydration of your framework component:</p>
<ul>
<li><code>client:load</code></li>
<li><code>client:only</code></li>
<li><code>client:visible</code></li>
<li><code>client:media</code></li>
<li><code>client:idle</code></li>
</ul>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/responsible-hydration-astro-plane.png" alt="Representing the client template directives on a priority - interactivity plane." width="2092" height="1634" loading="lazy">
<em>Representing the client template directives on a priority - interactivity plane.</em></p>
<h3 id="heading-clientload"><code>client:load</code></h3>
<p><code>client:load</code> should be used for high-priority interface elements that must be interactive as soon as possible.</p>
<ul>
<li>Priority: high</li>
<li>Interactivity: high</li>
</ul>
<p>We may go ahead and render our <code>UpvoteContent</code> component as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">import</span> { UpvoteContent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/UpvoteContent.jsx"</span>;
<span class="hljs-keyword">import</span> DefaultIslandLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/DefaultIslandLayout.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DefaultIslandLayout</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> <span class="hljs-attr">client:load</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">DefaultIslandLayout</span>&gt;</span></span>
</code></pre>
<p>Here are the hydration steps:</p>
<ol>
<li>Render the component HTML (not hydrated).</li>
<li>Wait for the page to load.</li>
<li>Load component JavaScript.</li>
<li>Hydrate component.</li>
</ol>
<p>The load event is fired when the page has loaded, including all dependent resources such as stylesheets, scripts, iframes, and images.</p>
<p>It’s important to note that clicking the upvote button will not trigger any upvotes before hydration.</p>
<h3 id="heading-clientonly"><code>client:only</code></h3>
<p><code>client:only</code> behaves similarly to <code>client:load</code>. It should be used for elements where you want to skip server-side rendering (the component will not be initially rendered to HTML) but make it interactive as soon as it’s shown to the user on the client.</p>
<ul>
<li>Priority: medium (we’re okay not showing the initial component HTML)</li>
<li>Interactivity: high (as soon as it’s shown to the user)</li>
</ul>
<p>We may go ahead and render our <code>UpvoteContent</code> component as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">import</span> { UpvoteContent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/UpvoteContent.jsx"</span>;
<span class="hljs-keyword">import</span> DefaultIslandLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/DefaultIslandLayout.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DefaultIslandLayout</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> <span class="hljs-attr">client:only</span>=<span class="hljs-string">"react"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">DefaultIslandLayout</span>&gt;</span></span>
</code></pre>
<p>It’s essential to pass the framework name as shown above. Otherwise, Astro doesn’t know what framework's JavaScript to load. This is because this isn’t determined on the server.</p>
<pre><code class="lang-js">&lt;ReactComponent client:only=<span class="hljs-string">"react"</span> /&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">PreactComponent</span> <span class="hljs-attr">client:only</span>=<span class="hljs-string">"preact"</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SvelteComponent</span> <span class="hljs-attr">client:only</span>=<span class="hljs-string">"svelte"</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">VueComponent</span> <span class="hljs-attr">client:only</span>=<span class="hljs-string">"vue"</span> /&gt;</span></span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SolidComponent</span> <span class="hljs-attr">client:only</span>=<span class="hljs-string">"solid-js"</span> /&gt;</span></span>
</code></pre>
<p>Here are the hydration steps:</p>
<ol>
<li>Do not render component HTML.</li>
<li>Wait for the page to load.</li>
<li>Load component JavaScript.</li>
<li>Hydrate component.</li>
</ol>
<p>The difference between <code>client:only</code> and <code>client:load</code> is whether to render a static component HTML before the element is interactive. <code>client:only</code> is particularly handy when rendering components requiring client (browser) APIs.</p>
<h3 id="heading-clientvisible"><code>client:visible</code></h3>
<p><code>client:visible</code> should be used for low-priority interface elements below the fold (far down the page) or resource-intensive. You don’t want to load them if the user never sees the component.</p>
<ul>
<li>Priority: low</li>
<li>Interactivity: low</li>
</ul>
<p>We may go ahead and render our <code>UpvoteContent</code> component as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">import</span> LargeMainContentLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/LargeMainContentLayout.astro"</span>;
<span class="hljs-keyword">import</span> { UpvoteContent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/UpvoteContent.jsx"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">LargeMainContentLayout</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> <span class="hljs-attr">client:visible</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">LargeMainContentLayout</span>&gt;</span></span>
</code></pre>
<p>Note that I’m importing a different <code>LargeMainContentLayout</code> layout in the code block above. The layout is responsible for pushing the island off the initial viewport.</p>
<p>Here are the hydration steps:</p>
<ol>
<li>Render component HTML.</li>
<li>Wait for the element to be visible (uses <code>IntersectionObserver</code> ).</li>
<li>Load component JavaScript.</li>
<li>Hydrate component.</li>
</ol>
<h3 id="heading-clientmedia"><code>client:media</code></h3>
<p><code>client:media</code> should be used for low-priority interface elements only visible on specific screen sizes, for example sidebar toggles.</p>
<ul>
<li>Priority: low</li>
<li>Interactivity: low</li>
</ul>
<p>We may go ahead and render our <code>UpvoteContent</code> component as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">import</span> { UpvoteContent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/UpvoteContent.jsx"</span>;
<span class="hljs-keyword">import</span> DefaultIslandLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/DefaultIslandLayout.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DefaultIslandLayout</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> <span class="hljs-attr">client:media</span>=<span class="hljs-string">"(max-width: 30em)"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">DefaultIslandLayout</span>&gt;</span></span>
</code></pre>
<p>Here are the hydration steps:</p>
<ol>
<li>Render component HTML</li>
<li>Check if the media query matches</li>
<li>Load component JavaScript</li>
<li>Hydrate component</li>
</ol>
<h3 id="heading-clientidle"><code>client:idle</code></h3>
<p><code>client:idle</code> should be used for low-priority interface elements that don’t need to be immediately interactive.</p>
<ul>
<li>Priority: medium</li>
<li>Interactivity: medium</li>
</ul>
<p>We may go ahead and render our <code>UpvoteContent</code> component as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">import</span> { UpvoteContent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/UpvoteContent.jsx"</span>;
<span class="hljs-keyword">import</span> DefaultIslandLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/DefaultIslandLayout.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DefaultIslandLayout</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> <span class="hljs-attr">client:idle</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">DefaultIslandLayout</span>&gt;</span></span>
</code></pre>
<p>Here’s the hydration step visualised:</p>
<ol>
<li>Render component HTML.</li>
<li>Wait for the page to load.</li>
<li>Wait for the <code>requestIdleCallback</code> event to be fired. If <code>requestIdleCallback</code> isn’t supported, use only the document <code>load</code> event.</li>
<li>Load component JavaScript.</li>
<li>Hydrate component.</li>
</ol>
<h2 id="heading-how-to-use-multiple-frameworks">How to Use Multiple Frameworks</h2>
<p>Theoretically, we can use multiple framework components in an Astro application. This is a powerful feature, but it shouldn’t be abused.</p>
<p>It does make for powerful demos of what’s possible with Astro. But there are only a few real-world cases where we might want to do this, like composing autonomous micro frontends on an Astro page.</p>
<p>Within an Astro component, the following is valid:</p>
<pre><code class="lang-js">---
 <span class="hljs-comment">// import different framework components </span>
 <span class="hljs-keyword">import</span> SpecialReactComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/
SpecialReactComponent.jsx'</span> 

 <span class="hljs-keyword">import</span> SpecialVueComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/
SpecialVueComponent.jsx'</span> 


<span class="hljs-keyword">import</span> SpecialSvelteComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/
SpecialSvelteComponent.jsx'</span> 
---

&lt;!-- render the components --&gt; 
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SpecialReactComponent</span> <span class="hljs-attr">client:load</span>/&gt;</span></span> 
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SpecialVueComponent</span> <span class="hljs-attr">client:idle</span>/&gt;</span></span> 
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">SpecialSvelteComponent</span> <span class="hljs-attr">client:load</span>/&gt;</span></span>
</code></pre>
<p>Let’s see a real example in practice.</p>
<h3 id="heading-an-upvote-counter-in-vue">An upvote counter in Vue</h3>
<p>Recall that we built the initial <code>UpvoteContent</code> component using React. We’ll now create the <code>UpvoteContent</code> component using Vue and render both components in our Astro project.</p>
<p>Here’s the annotated implementation:</p>
<pre><code class="lang-js">&lt;!-- 📂 src/components/UpvoteContent.vue --&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  data() {
   <span class="hljs-comment">// data properties used in the UI template </span>
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">upvoteCount</span>: <span class="hljs-number">0</span>,
      <span class="hljs-attr">maxUpvoteCount</span>: <span class="hljs-number">50</span>,
    };
  },
  <span class="hljs-attr">methods</span>: {
    <span class="hljs-comment">// method called when you click the upvote button</span>
    upvote() {
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.upvoteCount &lt; <span class="hljs-built_in">this</span>.maxUpvoteCount) {
        <span class="hljs-built_in">this</span>.upvoteCount++;
      }
    },
  },
};
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
      // <span class="hljs-attr">Attach</span> <span class="hljs-attr">a</span> <span class="hljs-attr">click</span> <span class="hljs-attr">event</span> <span class="hljs-attr">handler</span> <span class="hljs-attr">and</span> <span class="hljs-attr">invoke</span> "<span class="hljs-attr">upvote.</span>"
      @<span class="hljs-attr">click</span>=<span class="hljs-string">"upvote"</span>
    &gt;</span>    
     {/** Collapsed svg for brevity **/}      
      <span class="hljs-tag">&lt;<span class="hljs-name">svg</span> <span class="hljs-attr">..</span>/&gt;</span>
      Upvote
    <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        Vue
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{{ `${upvoteCount} upvotes` }}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

       {/** Increase the width of the div by "count percentage"**/}   
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">:style</span>=<span class="hljs-string">"{ width: `${upvoteCount}%` }"</span> /&gt;</span>

        {/** Render this section only if 
          the count is equal to the max count  **/}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>
        <span class="hljs-attr">v-if</span>=<span class="hljs-string">"upvoteCount === maxUpvoteCount"</span>
      &gt;</span>
        Max upvote reached
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span></span>
</code></pre>
<p>And that’s it!</p>
<h3 id="heading-how-to-render-different-framework-components">How to render different framework components</h3>
<p>The rendering process for framework components is essentially the same. Let’s go ahead and render the React and Vue <code>UpvoteContent</code> components on a new page, as shown below:</p>
<pre><code class="lang-js">&lt;!-- 📂 src/pages/multiple-frameworks.astro --&gt;
---
<span class="hljs-keyword">import</span> { UpvoteContent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/UpvoteContent.jsx"</span>;
<span class="hljs-keyword">import</span> UpvoteContentVue <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/UpvoteContent.vue"</span>;
<span class="hljs-keyword">import</span> DefaultIslandLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"../layouts/DefaultIslandLayout.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">DefaultIslandLayout</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> <span class="hljs-attr">client:load</span> /&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContentVue</span> <span class="hljs-attr">client:load</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">DefaultIslandLayout</span>&gt;</span></span>
</code></pre>
<ul>
<li>We create a new page in <code>pages/multiple-frameworks.astro</code>.</li>
<li>We import both React and Vue components.</li>
<li>We render both components in an identical pattern and with the same client directive, <code>client:load</code>.</li>
</ul>
<p>It’s also essential to add Vue support to the project by running the following:</p>
<pre><code class="lang-js">npx astro add vue
</code></pre>
<p>This will install the relevant Vue dependencies and add the integration support in the Astro config file.</p>
<p>Once that’s done, we may view the running application on route <code>/multiple-frameworks</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-03-13-at-15.39.40@2x.png" alt="The React and Vue component rendered in a single Astro page Route." width="2000" height="1197" loading="lazy">
<em>The React and Vue component rendered in a single Astro page Route.</em></p>
<p>As expected, both components are rendered and work just as expected.</p>
<h2 id="heading-how-to-share-state-between-component-islands">How to Share State Between Component Islands</h2>
<p>As we work with component islands in Astro, you will inevitably need to share certain application states between component islands.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/islands-share-state.png" alt="Sharing state between two upvote islands." width="2000" height="1389" loading="lazy">
<em>Sharing state between two upvote islands.</em></p>
<p>For example, let’s assume we want our <code>UpvoteContent</code> components to share the same counter values.</p>
<p>Regardless of the component framework, every framework has its construct for sharing UI state between components, for example between React or Vue components.</p>
<p>But when working within Astro components, we need a solution that works framework agnostic, that is it's not tied to a single framework.</p>
<p>Here are some tremendous framework-agnostic solutions we can choose from:</p>
<ul>
<li><strong>Signals</strong>: These are great for expressing state based on reactive principles. We may use <a target="_blank" href="https://github.com/preactjs/signals">signals from Preact</a>, <a target="_blank" href="https://github.com/tldraw/signia">signia from tldraw</a> or <a target="_blank" href="https://www.solidjs.com/docs/latest">Solid signals</a> outside a component context.</li>
<li><strong><a target="_blank" href="https://vuejs.org/guide/scaling-up/state-management.html#simple-state-management-with-reactivity-api">Vue’s reactivity API</a></strong>: This can be an excellent ready-to-use solution if you already utilise Vue components in your Astro project.</li>
<li><strong><a target="_blank" href="https://svelte.dev/tutorial/writable-stores">Svelte’s stores</a></strong>: This can also be a great out-of-the-box solution if you already use Svelte components in your Astro project.</li>
<li><strong><a target="_blank" href="https://github.com/nanostores/nanostores">Nano stores</a></strong>: This is a tiny framework-agnostic library for state management.</li>
</ul>
<p>In this example, we’ll use Nano stores mainly because they are lightweight (less than 1kb) and don’t add a lot of JavaScript footprint to our application.</p>
<h3 id="heading-how-nano-store-works">How nano store works</h3>
<p>At a high level, what we’re trying to achieve is to remove the state values from within our framework components and manage them via <code>nanastores</code>.</p>
<p>We’ll create a new <code>upvoteCounter</code> state variable within nanostore. We will then propagate changes to this state variable to our framework components.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/nanostore-share-variable.png" alt="Propagating state variables from nanostore." width="2000" height="1023" loading="lazy">
<em>Propagating state variables from nanostore.</em></p>
<h3 id="heading-install-nano-store">Install nano store</h3>
<p>To use nano store, we must install the library into our project. Run the following installation command:</p>
<pre><code class="lang-bash">npm install nanostores @nanostores/vue @nanostores/react
</code></pre>
<ul>
<li><code>nanostores</code> represents the base library for creating and managing our state values</li>
<li>To guarantee that the framework component is re-rendered whenever a state value changes, we will use the React and Vue integrations for nano stores through <code>@nanostores/react</code> and <code>@nanostores/vue</code>, respectively.</li>
</ul>
<h3 id="heading-create-the-state-value">Create the state value</h3>
<p>Our example includes sharing the upvote count value across multiple framework components.</p>
<p>To create a state value, nano stores use atoms to store strings, numbers, and arrays.</p>
<p>Let’s create an atom to hold the counter state variable:</p>
<pre><code class="lang-js">&lt;!-- 📂 src/stores/upvote.ts --&gt;
<span class="hljs-keyword">import</span> { atom } <span class="hljs-keyword">from</span> <span class="hljs-string">"nanostores"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> upvoteCountStore = atom(<span class="hljs-number">0</span>);
</code></pre>
<ul>
<li>We create a new file in <code>src/stores/upvote.ts</code>.</li>
<li>We import <code>atom</code> from <code>nanostore</code>.</li>
<li>We create a new state number value called <code>upvoteCountStore</code>.</li>
</ul>
<p>We may think of atoms as small pieces of state to be shared across components in our application.</p>
<h3 id="heading-how-to-use-the-state-value-in-framework-components">How to use the state value in framework components</h3>
<p>In the React component, we will leverage the <code>useStore</code> hook provided in <code>@nanostores/react</code> to retrieve the state value from the <code>upvoteCountStore</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/UpvoteContent.tsx</span>

<span class="hljs-keyword">import</span> { useStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nanostores/react"</span>;
<span class="hljs-keyword">import</span> { upvoteCountStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"../stores/upvote"</span>;

<span class="hljs-keyword">const</span> MAX_COUNT = <span class="hljs-number">50</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> UpvoteContent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-comment">// Get the state value from the created store </span>
  <span class="hljs-keyword">const</span> upvoteCount = useStore(upvoteCountStore);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">button</span>
        <span class="hljs-attr">onClick</span>=<span class="hljs-string">{()</span> =&gt;</span> {
          if (upvoteCount <span class="hljs-tag">&lt; <span class="hljs-attr">MAX_COUNT</span>) {
            //<span class="hljs-attr">Update</span> <span class="hljs-attr">the</span> <span class="hljs-attr">store</span> <span class="hljs-attr">via</span> <span class="hljs-attr">the</span> <span class="hljs-attr">set</span> <span class="hljs-attr">method</span>
            <span class="hljs-attr">upvoteCountStore.set</span>(<span class="hljs-attr">upvoteCount</span> + <span class="hljs-attr">1</span>);
          }
        }}
      &gt;</span>
      { /** The rest of the code stays the same **/}
        Upvote
      <span class="hljs-tag">&lt;/<span class="hljs-name">button</span>&gt;</span>
      { /** The rest of the code stays the same **/}
     <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
  );
};
</code></pre>
<p>I've annotated the code to make it easier to understand. Take a look.</p>
<p>With the Vue component, we may leverage <code>props</code> for reactivity as shown below:</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
<span class="hljs-keyword">import</span> { useStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nanostores/vue"</span>;
<span class="hljs-keyword">import</span> { upvoteCountStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"../stores/upvote"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> {
  <span class="hljs-comment">// setup props to be used in the UI template </span>
  setup(props) {
    <span class="hljs-keyword">return</span> {
      <span class="hljs-comment">// Set the value of the upvoteCount from the store</span>
      <span class="hljs-attr">upvoteCount</span>: useStore(upvoteCountStore),
      <span class="hljs-attr">maxUpvoteCount</span>: <span class="hljs-number">50</span>,
    };
  },

  <span class="hljs-attr">methods</span>: {
    upvote() {
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">this</span>.upvoteCount &lt; <span class="hljs-built_in">this</span>.maxUpvoteCount) {
        <span class="hljs-comment">// Update the store via the set method </span>
        upvoteCountStore.set(<span class="hljs-built_in">this</span>.upvoteCount + <span class="hljs-number">1</span>);
      }
    },
  },
};
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>

<span class="hljs-tag">&lt;<span class="hljs-name">template</span>&gt;</span>
  { /** The rest of the code stays the same **/}
<span class="hljs-tag">&lt;/<span class="hljs-name">template</span>&gt;</span>
</code></pre>
<p>Lovely!</p>
<p>Now, if we try the application, both framework components should have synced upvote values:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-03-15-at-07.20.20.png" alt="Synced upvote state values via nanostores." width="842" height="465" loading="lazy">
<em>Synced upvote state values via nanostores.</em></p>
<h2 id="heading-how-to-pass-props-and-children-to-framework-components">How to Pass Props and Children to Framework Components</h2>
<p>Most framework components support receiving data via props and children. These are equally supported when rendering framework components in Astro.</p>
<p>For example, we currently have the upvote button label hardcoded.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-19-at-18.06.54@2x.png" alt="The upvote label." width="944" height="656" loading="lazy">
<em>The upvote label.</em></p>
<p>We could make this dynamic via props as shown below:</p>
<pre><code class="lang-html">// 📂 src/pages/load.astro
---
import { UpvoteContent } from "../components/UpvoteContent.jsx";
import DefaultIslandLayout from "../layouts/DefaultIslandLayout.astro";
---

<span class="hljs-tag">&lt;<span class="hljs-name">DefaultIslandLayout</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> <span class="hljs-attr">client:load</span> <span class="hljs-attr">label</span>=<span class="hljs-string">"Click"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">DefaultIslandLayout</span>&gt;</span>
</code></pre>
<p>We’d then handle the prop in the <code>UpvoteContent</code> React component as usual:</p>
<pre><code class="lang-ts"><span class="hljs-comment">// 📂 src/components/UpvoteContent.tsx</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> UpvoteContent = <span class="hljs-function">(<span class="hljs-params">props: { label: <span class="hljs-built_in">string</span> }</span>) =&gt;</span> {
   <span class="hljs-comment">// ... render props.label </span>
}
</code></pre>
<p>It’s important to note that we can pass any primitive as props, and they will work as expected.</p>
<p>But be careful with function props. Function props will only work during server rendering and fail when used in a hydrated client component, for example as an event handler. This is because functions cannot be serialised (transferred from the server to the client).</p>
<p>Children are often treated as a prop type – depending on the framework component used. For example, React, Preact, and Solid use the special <code>children</code> prop, while Svelte and Vue use the <code>&lt;slot /&gt;</code> element. These are both supported when working with framework components in Astro.</p>
<p>For example, with our React <code>&lt;UpvoteContent /&gt;</code> component, we could go ahead and receive a component description as <code>children</code>:</p>
<pre><code class="lang-js">&lt;UpvoteContent client:load&gt; 
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">em</span>&gt;</span>An upvote counter created using React<span class="hljs-tag">&lt;/<span class="hljs-name">em</span>&gt;</span></span>
&lt;/UpvoteContent&gt;
</code></pre>
<p>This will change nothing until we explicitly handle the <code>children</code> prop within the <code>&lt;UpvoteContent&gt;</code> component, as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// The component accepts props as an argument</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> UpvoteContent = <span class="hljs-function">(<span class="hljs-params">props: PropsWithChildren&lt;{}&gt;</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> upvoteCount = useStore(upvoteCountStore);

  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
     {/** Render the content of the children prop**/}
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{props.children}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
        {/** The rest of the component goes here**/}
      <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-03-15-at-12.50.27.png" alt="Rendering the React component child element." width="893" height="476" loading="lazy">
<em>Rendering the React component child element.</em></p>
<p>With our Vue <code>&lt;UpvoteContent /&gt;</code> component, we could equally receive a component description as children:</p>
<pre><code class="lang-js"> &lt;UpvoteContentVue client:load&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">em</span>&gt;</span>An upvote counter created using Vue<span class="hljs-tag">&lt;/<span class="hljs-name">em</span>&gt;</span></span>
  &lt;/UpvoteContentVue&gt;
</code></pre>
<p>But we must reference this via a <code>&lt;slot&gt;</code> element. This is a fundamental difference in how libraries like React / Preact and Vue / Svelte deal with references to the children prop.</p>
<p>Here’s how to reference the children element in <code>UpvoteContentVue</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/UpvoteContent.vue</span>
&lt;template&gt;
 <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- the slot element renders the children element --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">slot</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span> 
   <span class="hljs-comment">&lt;!-- The rest of the template goes here --&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/template&gt;
</code></pre>
<p>Also, we may use multiple slots to group and reference children within our framework components.</p>
<p>Consider the following example with multiple children elements:</p>
<pre><code class="lang-js">---
 <span class="hljs-keyword">import</span> { UpvoteContent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/UpvoteContent.jsx"</span>
---


<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">ul</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"social-links"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://twitter.com/understanding-astro"</span>&gt;</span>Twitter<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">li</span>&gt;</span><span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"https://github.com/understanding-astro"</span>&gt;</span>GitHub<span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span><span class="hljs-tag">&lt;/<span class="hljs-name">li</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">ul</span>&gt;</span>

  <span class="hljs-tag">&lt;<span class="hljs-name">em</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"description"</span>&gt;</span>An upvote counter created using React<span class="hljs-tag">&lt;/<span class="hljs-name">em</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">UpvoteContent</span>&gt;</span></span>
</code></pre>
<p>Note that we have two children nodes referenced by the slot names <code>social-links</code> and <code>description</code>, respectively.</p>
<p>Within <code>&lt;UpvoteContent /&gt;</code>, we may reference these separately as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> UpvoteContent = <span class="hljs-function">(<span class="hljs-params">{props}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> (
    <span class="xml"><span class="hljs-tag">&lt;&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{props.description}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>{props.socialLinks}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
      {/** ... **/}
    <span class="hljs-tag">&lt;/&gt;</span></span>
  );
};
</code></pre>
<p>It is important to note that the <code>kebab-case</code> slot names in the Astro component are referenced as <code>camelCase</code> values on the <code>props</code> object.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/kebab_to_camel_case.png" alt="Reference the kebab-case slot names as camelCase in React or Preact." width="1684" height="278" loading="lazy">
<em>Reference the kebab-case slot names as camelCase in React or Preact.</em></p>
<p>In Svelte and Vue, the slots will be referenced using a <code>&lt;slot&gt;</code> element with a <code>name</code> attribute. Here’s the implementation in <code>&lt;UpvoteContentVue /&gt;</code> :</p>
<pre><code class="lang-js">&lt;template&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"description"</span> /&gt;</span></span>
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">slot</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"social-links"</span> /&gt;</span></span>
&lt;/template&gt;
</code></pre>
<p>Note how the slot <code>kebab-case</code> names are preserved.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-03-16-at-08.07.52.png" alt="Rendering the React and Vue component children elements." width="848" height="549" loading="lazy">
<em>Rendering the React and Vue component children elements.</em></p>
<h2 id="heading-nested-framework-components">Nested Framework Components</h2>
<p>In an Astro file, we may also nest framework components, that. ispass framework components as children. For example, the following is valid:</p>
<pre><code class="lang-js">&lt;DefaultIslandLayout&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> <span class="hljs-attr">client:load</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"description"</span>&gt;</span>
     <span class="hljs-comment">&lt;!-- This is a nested &lt;UpvoteContent /&gt; component --&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">UpvoteContent</span> <span class="hljs-attr">client:load</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">em</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"description"</span>&gt;</span>This is the nested component<span class="hljs-tag">&lt;/<span class="hljs-name">em</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">UpvoteContent</span>&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">UpvoteContent</span>&gt;</span></span>
&lt;/DefaultIslandLayout&gt;
</code></pre>
<p>As expected, this renders the nested <code>UpvoteContent</code> component:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-03-16-at-09.00.38.png" alt="Rendering nested framework components." width="803" height="548" loading="lazy">
<em>Rendering nested framework components.</em></p>
<p>Recursively rendering the same component is rarely the goal we want to achieve. But rendering nested framework components is powerful because we can compose an entire framework component application as we see fit.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/nesting-framework-component.png" alt="Nesting multiple child components to make a more significant application." width="1748" height="1949" loading="lazy">
<em>Nesting multiple child components to make a more significant application.</em></p>
<h2 id="heading-astro-island-gotchas">Astro Island Gotchas</h2>
<p>As developers, we are often responsible for inadvertently breaking things. Although debugging can be an enjoyable challenge, consider the following boundaries with Astro Islands.</p>
<h3 id="heading-1-do-not-use-an-astro-component-in-a-framework-component">1. Do not use an Astro component in a framework component</h3>
<p>Consider the following example of importing a <code>.astro</code> component and rendering it within a React component:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { OurAstroComponent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/OurAstroComponent"</span>

<span class="hljs-keyword">const</span> OurReactComponent = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">OurAstroComponent</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
}
</code></pre>
<pre><code class="lang-js">&lt;OurReactComponent client:load /&gt;
</code></pre>
<p>This is an invalid use. The reason is that the React component is rendered a React “island”. Consequently, the island should contain only valid React code. This is the same for other framework component islands.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/wrong-astro-island-composition.png" alt="Do not render an Astro component as a framework component child without a <slot>." width="1748" height="1432" loading="lazy">
<em>Do not render an Astro component as a framework component child without a &lt;slot&gt;.</em></p>
<p>To overcome this, consider using the slot pattern earlier discussed to pass static content from an Astro component:</p>
<pre><code class="lang-js">---
 <span class="hljs-keyword">import</span> { OurReactComponent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/OurReactComponent"</span>
<span class="hljs-keyword">import</span> { OurAstroComponent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/OurAstroComponent"</span>
--- 

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">OurReactComponent</span> <span class="hljs-attr">client:load</span>&gt;</span>
 <span class="hljs-comment">&lt;!-- pass Astro component as a child via a named slot --&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">OurAstroComponent</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"description"</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">OurReactComponent</span>&gt;</span></span>
</code></pre>
<h3 id="heading-2-do-not-hydrate-an-astro-component">2. Do not hydrate an Astro component</h3>
<p>Consider the following naive example to hydrate an Astro component using a client directive:</p>
<pre><code class="lang-js">---
 <span class="hljs-keyword">import</span> { OurAstroComponent } <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/OurAstroComponent"</span>
--- 

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">OurAstroComponent</span> <span class="hljs-attr">client:load</span> /&gt;</span></span>
</code></pre>
<p>This is invalid. Astro components have no client-side runtime. So use a <code>&lt;script&gt;</code> tag if you need to interactivity.</p>
<h2 id="heading-why-use-islands">Why Use Islands?</h2>
<p>Typically, most resources would place this section at the start of the chapter. But there are certain instances where it's more beneficial to showcase practical use cases before diving into the reasons behind them. Also, this approach could foster an intuitive understanding, which is what I've adopted here.</p>
<p>So, why focus on islands? What advantages do they offer?</p>
<h3 id="heading-1-performance">1. Performance</h3>
<p>One of the main advantages is improved performance. We can significantly enhance our site’s speed by converting most of our website to static HTML and selectively loading JavaScript through islands only when necessary. This is because JavaScript is one of the slowest assets to load per byte.</p>
<h3 id="heading-2-responsible-hydration">2. Responsible hydration</h3>
<p>If JavaScript is expensive to parse and execute, the decision to load it should be carefully taken (from a performance perspective). Also, no one solution fits all application types and use cases. As such, controlling when a component island is hydrated puts you in charge of your website's performance.</p>
<h3 id="heading-3-parallel-loading">3. Parallel loading</h3>
<p>Lastly, it’s essential to utilise parallel loading. This means that when we load several islands, they won’t have to wait for each other to become hydrated. Instead, each island is considered a distinct unit that loads and becomes hydrated independently, in isolation.</p>
<h2 id="heading-wrapping-up-this-chapter-3">Wrapping Up This Chapter</h2>
<p>In this chapter, we learned about component islands in Astro and how they work. We also explored why framework components are sometimes preferred over vanilla JavaScript or TypeScript via a <code>&lt;script&gt;</code> element.</p>
<p>We also went through the steps to use a framework component in an Astro application, including building a static site, installing the framework, and writing the component. </p>
<p>Finally, we experimented using a React and Vue component to demonstrate the use of framework components. See you in the next chapter!</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-137.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chapter five</em></p>
<h1 id="heading-chapter-5-oh-my-react-how-to-build-a-react-documentation-site-clone">Chapter 5: Oh my React! (How to Build a React Documentation Site Clone)</h1>
<p>In this chapter, we'll cover everything you need to know to develop rich content websites with real-world best practices. </p>
<p>This is a practical section best served with you coding along. To view the complete application, see the <a target="_blank" href="https://github.com/understanding-astro/react.dev-astro">GitHub repo</a>. </p>
<h2 id="heading-what-youll-learn-4">What You’ll Learn</h2>
<ul>
<li>How to style Astro projects with Tailwind.</li>
<li>Several syntax highlighting solutions for Astro.</li>
<li>How to leverage content collections for scalable and type-safe development.</li>
<li>Understand dynamic routing in Astro.</li>
</ul>
<h2 id="heading-set-up-the-starter-project">Set Up the Starter Project</h2>
<p>We’ve spent ample time learning the ins and outs of building static websites with Astro. So, in this chapter, we will not start from scratch.</p>
<p>Instead, we’ll begin with a basic static project we’ll build upon throughout the chapter.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/project-shell.png" alt="Building from a starter project " width="1780" height="767" loading="lazy">
<em>Building from a starter project</em></p>
<p>In this chapter, we will adopt a solution-oriented approach similar to the kind that detectives use. We aim to solve various <code>TODOs</code> scattered throughout the starter project.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/todos.png" alt="Solving small isolated problems" width="1507" height="691" loading="lazy">
<em>Solving small isolated problems</em></p>
<p>The reason for this is to ignore the concepts you've already learned and focus on learning new concepts or consolidating older concepts via practice — solving isolated problems.</p>
<p>To get started, go ahead and clone the project:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/understanding-astro/react.dev-astro.git
</code></pre>
<p>Then change directories:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> react.dev-astro
</code></pre>
<p>Finally, checkout to the <code>clean-slate</code> branch I’ve prepared so we can systematically build upon the base application.</p>
<pre><code class="lang-bash">git checkout clean-slate
</code></pre>
<h2 id="heading-install-the-dependencies">Install the Dependencies</h2>
<p>Go ahead and install the project’s dependencies via the following:</p>
<pre><code class="lang-bash">npm install
</code></pre>
<p>Then install the Astro <code>react</code> integration:</p>
<pre><code class="lang-bash">npx astro add react
</code></pre>
<p>When prompted, type “y” to accept each prompt. “y” means “yes”!</p>
<p>The complete installation will add all relevant React dependencies and updates the <code>astro.config.mjs</code> project configuration file.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-23-at-08.11.48.png" alt="Image" width="818" height="337" loading="lazy">
<em>Installing the React integration and dependencies</em></p>
<p>Finally, go ahead and install the <code>mdx</code> integration. I’ll describe the what and why later in the chapter. For now, go ahead and install the integration by running the following:</p>
<pre><code class="lang-bash">npx astro add mdx
</code></pre>
<p>This will install the <code>@astrojs/mdx</code> integration and also update the <code>astro.config.mjs</code> project configuration file.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-23-at-08.13.42.png" alt="Image" width="783" height="261" loading="lazy">
<em>Installing the MDX integration</em></p>
<p>Now run the application:</p>
<pre><code class="lang-bash">npm start
</code></pre>
<p>This will run the application in an available local port – the default <code>localhost:3000</code>.</p>
<p>Visit the local server and you’ll find the base unstyled application running in the browser as shown below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-23-at-08.16.14.png" alt="The unstyled homepage" width="1554" height="960" loading="lazy">
<em>The unstyled homepage</em></p>
<p>I’ve got to say that’s one ugly-looking page.</p>
<p>We’ll fix that next.</p>
<h2 id="heading-how-to-style-astro-projects-with-tailwind">How to Style Astro Projects with Tailwind</h2>
<p>Love or hate it, CSS is how we make beautiful web applications.</p>
<p>In Chapter One, we wrote the styles for the personal website by hand, that is by writing out every CSS declaration. But in this chapter, we will use a CSS framework called Tailwind.</p>
<p>So, what’s Tailwind?</p>
<p>An overly simple definition would be, Tailwind is the modern <a target="_blank" href="https://getbootstrap.com/">bootstrap</a>. Never used Bootstrap? Then think of Tailwind as a utility-first CSS framework that provides class names like <code>flex</code>, <code>text-lg</code>, <code>items-center</code> and many more that you can apply to your markup for styles.</p>
<p>Tailwind will enable us to build modern-looking websites — fast.</p>
<h3 id="heading-how-to-install-tailwind">How to install Tailwind</h3>
<p>Keep the project running in your terminal and open another terminal tab. Run the following install command:</p>
<pre><code class="lang-bash">npx astro add tailwind
</code></pre>
<p>This will install the Astro tailwind integration in the project and update the project configuration.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-24-at-08.16.12.png" alt="Image" width="788" height="355" loading="lazy">
<em>Installing the Astro Tailwind integration</em></p>
<p>Once the installation is complete, the existing application styles will now take effect. Visit the application on your local port to see the styled application.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-24-at-08.17.17.png" alt="Image" width="1693" height="1014" loading="lazy">
<em>The styled application</em></p>
<p>What a difference styling makes!</p>
<p>Take your time and browse the different pages of the styled application.</p>
<h3 id="heading-how-does-tailwind-work">How does Tailwind work?</h3>
<p>Using Tailwind in Astro is straightforward. Install the Tailwind integration and provide a <code>class</code> attribute with Tailwind utility classes in your component markup.</p>
<p>For example, consider the styled text “The library for web and native user interfaces” on the project homepage:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-03-at-06.50.11@2x.png" alt="Image" width="1671" height="957" loading="lazy">
<em>The homepage subtitle</em></p>
<p>Now, consider the code responsible for the styles:</p>
<pre><code class="lang-js"><span class="hljs-comment">// pages/index.astro</span>
<span class="hljs-comment">// ...</span>
&lt;p
   <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"max-w-lg py-1 text-center font-display text-4xl leading-snug text-secondary dark:text-primary-dark md:max-w-full"</span>
 &gt;
   The library <span class="hljs-keyword">for</span> web and native user interfaces
&lt;/p&gt;
</code></pre>
<p>In the example above, the classes applied are as shown below:</p>
<pre><code class="lang-html">"max-w-lg py-1 text-center font-display text-4xl leading-snug text-secondary dark:text-primary-dark md:max-w-full"
</code></pre>
<p>While this is not a Tailwind book, it’s only fair to give a general explanation of what’s going on here.</p>
<p>Firstly, most Tailwind utility classes are well-named and you can infer what they do. Others are not so well-named.</p>
<p>If you’re coding along in VSCode, I recommend installing the official Tailwind integration:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-03-at-06.55.50@2x.png" alt="Installing the official VSCode Tailwind plugin" width="2000" height="472" loading="lazy">
<em>Installing the official VSCode Tailwind plugin</em></p>
<p>If you’re not using VSCode, consider finding your <a target="_blank" href="https://tailwindcss.com/docs/editor-setup">editor setup</a> in the official Tailwind docs.</p>
<p>Installing the integration brings a lot of benefits. The important benefit I want to highlight here is you can hover over any of the Tailwind utility classes to see the exact CSS property value the class corresponds to.</p>
<p>For example, hovering over the <code>max-w-lg</code> displays the CSS property value for the utility class as shown below:</p>
<pre><code class="lang-css"><span class="hljs-selector-class">.max-w-lg</span> {
    <span class="hljs-attribute">max-width</span>: <span class="hljs-number">32rem</span><span class="hljs-comment">/* 512px */</span>;
}
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-03-at-06.58.37@2x.png" alt="Image" width="1808" height="630" loading="lazy">
<em>Hovering over Tailwind classes</em></p>
<p>This is very helpful because you can now inspect whatever classes are added to any markup in the project.</p>
<h3 id="heading-tailwind-configuration">Tailwind configuration</h3>
<p>Upon installing Tailwind, it ships with its default theme.</p>
<p>It’s not a bad theme, but when you build projects, you likely want control over the project theme.</p>
<p>In our example, we want a theme that's modeled after the official React documentation theme.</p>
<p>To customise Tailwind, we can provide a <code>tailwind.config.js</code> file where we can define our project’s fonts, colour palette, type scale, border radius values, breakpoints and much more.</p>
<p>Look at the <code>tailwind.config.cjs</code> file in the project’s root. This is where the project’s Tailwind configuration magic happens.</p>
<p>For more details on customising Tailwind, you can consult the <a target="_blank" href="https://tailwindcss.com/docs/theme">official documentation</a>.</p>
<h2 id="heading-typescript-import-alias">Typescript Import Alias</h2>
<p>Let’s be honest, no one likes those ugly relative imports, eh?</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> MyComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'../../components/MyComponent.astro</span>
</code></pre>
<p>Ugh!!</p>
<p>C’mon, we can do better.</p>
<p>This is where import aliases come in. The easiest way to get this set up in an Astro project is to define the aliases in the <code>tsconfig.json</code> file.</p>
<p>For example, we may do the following:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 tsconfig.json </span>

{
  <span class="hljs-string">"compilerOptions"</span>: {
    <span class="hljs-string">"baseUrl"</span>: <span class="hljs-string">"."</span>,
    <span class="hljs-string">"paths"</span>: {
      <span class="hljs-string">"@components/*"</span>: [<span class="hljs-string">"src/components/*"</span>],
    }
  }
}
</code></pre>
<p>We’re essentially mapping any directories in the <code>src/components</code> import path to <code>@components</code>.</p>
<p>Now, wait for it.</p>
<p>The result of this is we can take our previous ugly import path and turn it into a work of art as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Before</span>
<span class="hljs-keyword">import</span> MyComponent <span class="hljs-keyword">from</span> <span class="hljs-string">'../../components/MyComponent.astro

// After 
import MyComponent from '</span>@components/MyComponent.astro<span class="hljs-string">'</span>
</code></pre>
<p>Beautiful and clean, isn’t it?</p>
<p>The reason I mention this is the starter project has been set up to use import aliases. So, don’t get confused.</p>
<p>Go ahead and look in the <code>tsconfig.json</code> file where you’ll find the following import aliases:</p>
<pre><code class="lang-js"><span class="hljs-string">"paths"</span>: {
   <span class="hljs-string">"@components/*"</span>: [<span class="hljs-string">"src/components/*"</span>],
   <span class="hljs-string">"@layouts/*"</span>: [<span class="hljs-string">"src/layouts/*"</span>],
   <span class="hljs-string">"@utils/*"</span>: [<span class="hljs-string">"src/utils/*"</span>]
}
</code></pre>
<p>You’re welcome 😉</p>
<h2 id="heading-islands-and-colocating-page-components">Islands and Colocating Page Components</h2>
<p>We’ve learned that appropriate file types in the <code>src/pages</code> directory get transformed into HTML pages.</p>
<p>But what if we need to have some files collocated in the <code>src/pages</code> directory without being transformed into accompanying <code>HTML</code> pages?</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/exclude_page_intro.png" alt="Colocating files in the pages directory" width="883" height="563" loading="lazy">
<em>Colocating files in the pages directory</em></p>
<p>This can be helpful for collocating tests, utilities, and components along the associating pages.</p>
<p>Well, there’s a solution for that.</p>
<p>To exclude a valid page file type in the <code>src/pages</code> directory from being compiled into an associating HTML page, prefix the file name with an underscore <code>_</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/prefix_exclude_page.png" alt="Prefix file name with a underscore to not transform into HTML pages" width="883" height="642" loading="lazy">
<em>Prefix file name with a underscore to not transform into HTML pages</em></p>
<p>For example, take a look at the <code>pages/_components/Home</code> directory in the project.</p>
<p>This directory contains a handful of components that aren’t meant to be reusable across the project. They only exist to be used on the project’s homepage.</p>
<p>To exclude these from being separate browser pages, note how the <code>_components</code> directory is named.</p>
<p>As an example, if you visited <code>/_components/Home/Code</code> in the browser, this will return a <code>404</code>. Even though the <code>Code</code> components exist, it is not a page.</p>
<p>Now, let’s bring our knowledge of collocated components and Astro islands together to solve our first TODO in the project.</p>
<p>Take a look at the <code>index.astro</code> and consider the <code>TODO</code> to render the <code>Video</code> React component as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
❗️ &lt;Code <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"text-white"</span>&gt;TODO:&lt;/Code&gt; (Astro Island): Render the ...
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-05-at-08.40.18@2x.png" alt="TODO: Render the Video React component island" width="2642" height="1216" loading="lazy">
<em>TODO: Render the Video React component island</em></p>
<p>Now consider the annotated solution below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
=== 
<span class="hljs-comment">// Import the Video component from "_components ..." </span>
<span class="hljs-keyword">import</span> { Video } <span class="hljs-keyword">from</span> <span class="hljs-string">"./_components/home/Video"</span>;
<span class="hljs-comment">// ...</span>
--- 
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">ExampleResultPanel</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"right-content"</span>&gt;</span>
  {/** Render the Video component. NB: this is a React component **/}
   <span class="hljs-tag">&lt;<span class="hljs-name">Video</span>
     <span class="hljs-attr">client:visible</span> {/** 👈 <span class="hljs-attr">Add</span> <span class="hljs-attr">the</span> <span class="hljs-attr">client</span> <span class="hljs-attr">directive</span> **/}
     <span class="hljs-attr">video</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">title:</span> "<span class="hljs-attr">My</span> <span class="hljs-attr">video</span>", <span class="hljs-attr">description:</span> "<span class="hljs-attr">Video</span> <span class="hljs-attr">description</span>" }}
    /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">ExampleResultPanel</span>&gt;</span></span>
</code></pre>
<ul>
<li>Render the <code>Video</code> React component</li>
<li>Pass a <code>client:visible</code> attribute to hydrate the island as soon as the component is visible</li>
<li>Finally pass the required <code>video</code> object props to the <code>Video</code> component: <code>{title: "my video", description: "Video description"}</code>.</li>
</ul>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-05-at-08.39.19@2x.png" alt="The rendered video island" width="2000" height="935" loading="lazy">
<em>The rendered video island</em></p>
<p>Similarly, let’s resolve the second TODO. This time around we’ll render multiple <code>Video</code> components.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro </span>
❗️ &lt;Code <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"text-white"</span>&gt;TODO:&lt;/Code&gt; (Astro Island): Render two ...
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-05-at-08.43.18@2x.png" alt="TODO: Render two React component islands " width="2468" height="1019" loading="lazy">
<em>TODO: Render two React component islands</em></p>
<p>Consider the solution below:</p>
<pre><code class="lang-js">&lt;ExampleResultPanel slot=<span class="hljs-string">"right-content"</span>&gt;
  <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex w-full flex-col gap-4"</span>&gt;</span>
    {/** ... **/}
    {/** Render both islands **/}
    <span class="hljs-tag">&lt;<span class="hljs-name">Video</span>
      <span class="hljs-attr">client:visible</span>
      <span class="hljs-attr">video</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">title:</span> "<span class="hljs-attr">My</span> <span class="hljs-attr">video</span>", <span class="hljs-attr">description:</span> "<span class="hljs-attr">Video</span> <span class="hljs-attr">description</span>" }}
    /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Video</span>
      <span class="hljs-attr">client:visible</span>
      <span class="hljs-attr">video</span>=<span class="hljs-string">{{</span> <span class="hljs-attr">title:</span> "<span class="hljs-attr">My</span> <span class="hljs-attr">video</span>", <span class="hljs-attr">description:</span> "<span class="hljs-attr">Video</span> <span class="hljs-attr">description</span>" }}
    /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
&lt;/ExampleResultPanel&gt;
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-05-at-08.45.15@2x.png" alt="The rendered Astro islands" width="2000" height="1000" loading="lazy">
<em>The rendered Astro islands</em></p>
<h2 id="heading-syntax-highlighting">Syntax Highlighting</h2>
<p>I never understood the intricacies of syntax highlighting until I started researching this section of the book. It’s great how much is abstracted in libraries.</p>
<p>Anyway, I’ll skip the nuances and provide what I believe to be the most important bits.</p>
<p>So, how do we tackle syntax highlighting in an Astro application?</p>
<p>By default, Astro uses <a target="_blank" href="https://github.com/shikijs/shiki">Shiki</a> – a syntax highlighting library under the hood. Broadly speaking, there are two ways to go about syntax highlighting your code blocks in an Astro component.</p>
<p>Let’s have a look at these.</p>
<h3 id="heading-the-default-code-component">The default Code component</h3>
<p>Astro ships with a <code>&lt;Code /&gt;</code> component that provides syntax highlights at build time.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/code_component.png" alt="The Code component renders to HTML and inline styles without any Javascript" width="1907" height="879" loading="lazy">
<em>The Code component renders to HTML and inline styles without any Javascript</em></p>
<p>By implication, there’s no runtime overhead to this method of syntax highlighting as no computations are done at runtime and the eventual result is a bunch of elements with inline styles.</p>
<p>This is powered by Shiki.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-25-at-08.35.52.png" alt="Sample syntax highlighted DOM output" width="867" height="595" loading="lazy">
<em>Sample syntax highlighted DOM output</em></p>
<p>Let’s go back to our starter project and resolve another TODO.</p>
<pre><code class="lang-js">📂 src/pages/index.astro

<span class="hljs-comment">// ...</span>
❗️ &lt;Code <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"text-white"</span>&gt;TODO:&lt;/Code&gt; Replace <span class="hljs-keyword">with</span> Syntax highlighted code
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-05-at-16.06.25@2x.png" alt="TODO: Add syntax highlighted code block" width="2748" height="1457" loading="lazy">
<em>TODO: Add syntax highlighted code block</em></p>
<p>The goal here is to provide syntax-highlighted code within the component markup.</p>
<p>To solve this, we’ll leverage the <code>Code</code> component from Astro as shown in the annotated code block below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-comment">// import Code from "astro/components" </span>
<span class="hljs-keyword">import</span> { Code <span class="hljs-keyword">as</span> AstroCode } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/components"</span>;
<span class="hljs-comment">//... other imports </span>
---

<span class="hljs-comment">// ...Render the component and pass the code and lang string props</span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">slot</span>=<span class="hljs-string">"left-content"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">AstroCode</span>
            <span class="hljs-attr">code</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">function</span> <span class="hljs-attr">Video</span>({ <span class="hljs-attr">video</span> }) {
  <span class="hljs-attr">return</span> (
    &lt;<span class="hljs-attr">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Thumbnail</span> <span class="hljs-attr">video</span>=<span class="hljs-string">{video}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{video.url}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{video.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{video.description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">LikeButton</span> <span class="hljs-attr">video</span>=<span class="hljs-string">{video}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  );
}`}
    lang="jsx" {/** 👈 code language for syntax highlighting **/}
   /&gt;
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-25-at-13.04.02@2x.png" alt="The syntax highlighted code block" width="1406" height="1040" loading="lazy">
<em>The syntax highlighted code block</em></p>
<p>Since the code snippets are just good old HTML DOM nodes, we can apply some styles on the parent <code>div</code> to style them further as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
&lt;div
   slot=<span class="hljs-string">"left-content"</span>
   <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"[&amp;_pre]:!bg-transparent [&amp;_pre]:!text-sm [&amp;_pre]:!leading-6"</span>&gt;
    <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AstroCode</span> <span class="hljs-attr">...</span> /&gt;</span></span>
&lt;/div&gt;
</code></pre>
<p>This will reduce the size of the font, reduce the type leading and make the code background transparent. Note that the square braces are how we write arbitrary <a target="_blank" href="https://tailwindcss.com/docs/adding-custom-styles#using-arbitrary-values">custom styles</a> in Tailwind.</p>
<p>See the results below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-25-at-13.03.25@2x.png" alt="Better styled syntax highlighted code block" width="1396" height="912" loading="lazy">
<em>Better styled syntax highlighted code block</em></p>
<p>Much better eh?</p>
<p>We can go ahead and do the same for the other <code>TODO</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
❗️ &lt;Code <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"text-white"</span>&gt;TODO:&lt;/Code&gt; Replace <span class="hljs-keyword">with</span> Syntax highlighted code
</code></pre>
<p>Consider the identical solution below:</p>
<pre><code class="lang-js">&lt;div
   slot=<span class="hljs-string">"left-content"</span>
   {<span class="hljs-comment">/** Similar style as before. Leverages Tailwind **/</span>}
   <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"[&amp;_pre]:!bg-transparent [&amp;_pre]:!text-sm [&amp;_pre]:!leading-6"</span>
        &gt;
          <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AstroCode</span>
            <span class="hljs-attr">code</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">function</span> <span class="hljs-attr">VideoList</span>({ <span class="hljs-attr">videos</span>, <span class="hljs-attr">emptyHeading</span> }) {
  <span class="hljs-attr">const</span> <span class="hljs-attr">count</span> = <span class="hljs-string">videos.length;</span>
  <span class="hljs-attr">let</span> <span class="hljs-attr">heading</span> = <span class="hljs-string">emptyHeading;</span>
  <span class="hljs-attr">if</span> (<span class="hljs-attr">count</span> &gt;</span> 0) {
    const noun = count &gt; 1 ? 'Videos' : 'Video';
    heading = count + ' ' + noun;
  }
  return (
    <span class="hljs-tag">&lt;<span class="hljs-name">section</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>{heading}<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
      {videos.map(video =&gt;
        <span class="hljs-tag">&lt;<span class="hljs-name">Video</span> <span class="hljs-attr">key</span>=<span class="hljs-string">{video.id}</span> <span class="hljs-attr">video</span>=<span class="hljs-string">{video}</span> /&gt;</span>
      )}
    <span class="hljs-tag">&lt;/<span class="hljs-name">section</span>&gt;</span>
  );
}`}
   lang="jsx"
 /&gt;</span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-25-at-13.05.02@2x.png" alt="The syntax highlighted code block" width="1406" height="1095" loading="lazy">
<em>The syntax highlighted code block</em></p>
<p>The default <code>Code</code> component also supports all the official Shiki <a target="_blank" href="https://github.com/shikijs/shiki/blob/main/docs/themes.md#all-themes">themes</a>. For example, we can change the component theme to <code>poimandres</code> as shown below:</p>
<pre><code class="lang-js">&lt;AstroCode
    <span class="hljs-comment">// ...</span>
   lang=<span class="hljs-string">"jsx"</span>
   theme=<span class="hljs-string">"poimandres"</span>
 /&gt;
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-25-at-13.15.33@2x.png" alt="The poimandres theme" width="1422" height="930" loading="lazy">
<em>The poimandres theme</em></p>
<p>Let’s consider the pros and cons of using the default <code>Code</code> component provided by Astro.</p>
<h4 id="heading-pros">Pros</h4>
<ul>
<li>Easy to use</li>
<li>Great results for low effort</li>
<li>Lots of available themes by default</li>
</ul>
<h4 id="heading-cons">Cons</h4>
<ul>
<li>More work is required to customise your themes, for example our www.react.dev clone requires its custom theme</li>
<li>No default support for dark and light theme</li>
</ul>
<h3 id="heading-bring-your-theme">Bring your theme</h3>
<p>Using your specific syntax themes is probably not the top of your list.</p>
<p>But Shiki supports the same syntax for VSCode themes. For example, we could load some custom open-source VSCode theme (or build on top of it) for our code blocks.</p>
<p>Let’s take a look at <a target="_blank" href="https://github.com/sdras/night-owl-vscode-theme">Nightowl</a>, a VS Code dark theme for contrast for nighttime coding.</p>
<p>Go ahead and copy the code <a target="_blank" href="https://raw.githubusercontent.com/sdras/night-owl-vscode-theme/main/themes/Night%20Owl-color-theme.json">snippet theme</a> to a <code>src/snippet-theme.json</code> file.</p>
<p>Next, we’ll write a simple component to load our custom theme as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/Shiki.astro</span>

---
<span class="hljs-keyword">import</span> type { Lang } <span class="hljs-keyword">from</span> <span class="hljs-string">"shiki"</span>;

<span class="hljs-comment">// Similar to Astro's Code component, this is built on shiki</span>
<span class="hljs-keyword">import</span> shiki, { getHighlighter } <span class="hljs-keyword">from</span> <span class="hljs-string">"shiki"</span>;

<span class="hljs-comment">// Similar to Astro's Code component, receive lang and code as props</span>
type Props = {
  <span class="hljs-attr">lang</span>: Lang;
  code: string;
};

<span class="hljs-keyword">const</span> { code = <span class="hljs-string">""</span>, lang = <span class="hljs-string">"jsx"</span> } = Astro.props;

<span class="hljs-comment">// 👀 Load the custom theme</span>
<span class="hljs-keyword">const</span> theme = <span class="hljs-keyword">await</span> shiki.loadTheme(<span class="hljs-string">"../../snippet-theme.json"</span>);

<span class="hljs-keyword">const</span> highlighter = <span class="hljs-keyword">await</span> getHighlighter({
  theme,
  <span class="hljs-attr">langs</span>: [lang],
});
---

{<span class="hljs-comment">/** 
  A fragment is an available Astro component. Use Fragment to prevent unnecessary markup.
The set:html directive is used to inject an HTML string into an element e.g., similar to el.innerHTML.
**/</span>}
&lt;Fragment
  <span class="hljs-attr">set</span>:html={highlighter.codeToHtml(code, {
    lang,
  })}
/&gt;
</code></pre>
<p>Import and use the new component:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-keyword">import</span> Shiki <span class="hljs-keyword">from</span> <span class="hljs-string">"@components/Shiki.astro"</span>;
<span class="hljs-comment">// ... </span>
---

<span class="hljs-comment">// Change AstroCode to Shiki (new component) </span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Shiki</span>
 <span class="hljs-attr">code</span>=<span class="hljs-string">{</span>`<span class="hljs-attr">function</span> <span class="hljs-attr">Video</span>({ <span class="hljs-attr">video</span> }) {
  <span class="hljs-attr">return</span> (
    &lt;<span class="hljs-attr">div</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">Thumbnail</span> <span class="hljs-attr">video</span>=<span class="hljs-string">{video}</span> /&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">a</span> <span class="hljs-attr">href</span>=<span class="hljs-string">{video.url}</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">h3</span>&gt;</span>{video.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h3</span>&gt;</span>
        <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{video.description}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
      <span class="hljs-tag">&lt;/<span class="hljs-name">a</span>&gt;</span>
      <span class="hljs-tag">&lt;<span class="hljs-name">LikeButton</span> <span class="hljs-attr">video</span>=<span class="hljs-string">{video}</span> /&gt;</span>
    <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
  );
}`}
  lang="jsx"
/&gt;</span>
</code></pre>
<p>And there we go! We’ve successfully loaded a custom theme.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-06-25-at-13.55.54@2x.png" alt="Comparing the previous highlighted code with the new Night Owl theme" width="1340" height="1657" loading="lazy">
<em>Comparing the previous highlighted code with the new Night Owl theme</em></p>
<p>For more customisations, we could spend time tweaking the different theme tokens in the <code>snippet-theme.json</code> file.</p>
<h4 id="heading-pros-1">Pros</h4>
<ul>
<li>Flexibility: we can customise the theme tokens as granularly as needed</li>
</ul>
<h4 id="heading-cons-1">Cons</h4>
<ul>
<li>Requires more work</li>
<li>Support for dark and light theme</li>
</ul>
<h3 id="heading-handling-light-and-dark-themes">Handling light and dark themes</h3>
<p>Supporting light and dark themes in Shiki (the underlying Astro syntax highlighter) is tricky because Shiki generates themes at build time.</p>
<p>At the time a user toggles the site theme, no changes will be made to the syntax highlighting since it was generated at build time.</p>
<p>When working with Astro components, a simple solution is to leverage CSS variables.</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> { Code <span class="hljs-keyword">as</span> AstroCode } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/components"</span>;
---

<span class="hljs-comment">// Among, other properties, pass a "css-variables" theme prop to the Code component </span>
 <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">AstroCode</span> <span class="hljs-attr">theme</span>=<span class="hljs-string">"css-variables"</span> /&gt;</span></span>
</code></pre>
<p>Then provide style tokens for both dark and light themes. Remember that this should be global. For example, we may do this in the <code>Baselayout.astro</code> layout component as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/BaseLayout.astro</span>
&lt;style is:<span class="hljs-built_in">global</span>&gt;
  @media (prefers-color-scheme: dark) {
    :root {
      --astro-code-color-text: #ffffff;
      --astro-code-color-background: black;
      --astro-code-token-constant: #<span class="hljs-number">86</span>d9ca;
      --astro-code-token-string: #<span class="hljs-number">977</span>cdc;
      --astro-code-token-comment: #<span class="hljs-number">757575</span>;
      --astro-code-token-keyword: #<span class="hljs-number">77</span>b7d7;
      --astro-code-token-parameter: #ffffff;
      --astro-code-token-<span class="hljs-function"><span class="hljs-keyword">function</span>: #86<span class="hljs-title">d9ca</span>;
      --<span class="hljs-title">astro</span>-<span class="hljs-title">code</span>-<span class="hljs-title">token</span>-<span class="hljs-title">string</span>-<span class="hljs-title">expression</span>: #<span class="hljs-title">c64640</span>;
      --<span class="hljs-title">astro</span>-<span class="hljs-title">code</span>-<span class="hljs-title">token</span>-<span class="hljs-title">punctuation</span>: #<span class="hljs-title">ffffff</span>;
      --<span class="hljs-title">astro</span>-<span class="hljs-title">code</span>-<span class="hljs-title">token</span>-<span class="hljs-title">link</span>: #977<span class="hljs-title">cdc</span>;
    }
  }

  :<span class="hljs-title">root</span> </span>{
    --astro-code-color-text: #<span class="hljs-number">24292</span>e;
    --astro-code-color-background: #ffffff;
    --astro-code-token-constant: #<span class="hljs-number">032</span>f62;
    --astro-code-token-string: #<span class="hljs-number">032</span>f62;
    --astro-code-token-comment: #<span class="hljs-number">6</span>a737d;
    --astro-code-token-keyword: #d73a49;
    --astro-code-token-parameter: #<span class="hljs-number">24292</span>e;
    --astro-code-token-<span class="hljs-function"><span class="hljs-keyword">function</span>: #6<span class="hljs-title">f42c1</span>;
    --<span class="hljs-title">astro</span>-<span class="hljs-title">code</span>-<span class="hljs-title">token</span>-<span class="hljs-title">string</span>-<span class="hljs-title">expression</span>: #<span class="hljs-title">c64640</span>;
    --<span class="hljs-title">astro</span>-<span class="hljs-title">code</span>-<span class="hljs-title">token</span>-<span class="hljs-title">punctuation</span>: #<span class="hljs-title">ffffff</span>;
    --<span class="hljs-title">astro</span>-<span class="hljs-title">code</span>-<span class="hljs-title">token</span>-<span class="hljs-title">link</span>: #977<span class="hljs-title">cdc</span>;
  }
&lt;/<span class="hljs-title">style</span>&gt;</span>
</code></pre>
<p>If dark and light theme syntax highlighting is critical for your application, take a look at the <a target="_blank" href="https://github.com/shikijs/shiki/blob/main/docs/themes.md#theming-with-css-variables">official documentation</a> for more information.</p>
<h2 id="heading-how-to-get-started-with-content-collections">How to Get Started with Content Collections</h2>
<p>Consider building a large application driven by a lot of content – whether that’s Markdown (<code>/md</code>), MDX (<code>.mdx</code>), JSON (<code>.json</code>) or YAML (<code>.yaml</code>) files.</p>
<p>One solution to best organise the project’s content could be to save the content data in a database where we can validate the document schema and make sure the required content fits the data model we desire.</p>
<p>We may visually model these as collections of data saved in a database with a predefined data schema.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/predefined_schema_db.png" alt="Modelling data with a predefined schema in a database" width="966" height="289" loading="lazy">
<em>Modelling data with a predefined schema in a database</em></p>
<p>With Astro projects, we don’t particularly need a database to store and enforce our content data models.</p>
<p>Enter content collections.</p>
<p>Regardless of the size of the Astro project, content collections are the best way to organise our content document, validate the structure of the document and also enjoy out-of-the-box TypeScript support when querying or manipulating the content collection.</p>
<p>So, what’s a content collection?</p>
<p>A content collection is any top-level directory in the <code>src/content</code> folder of an Astro project.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/content_collections.png" alt="Content collections - top directories in src/content" width="297" height="379" loading="lazy">
<em>Content collections - top directories in src/content</em></p>
<p>Note that the <code>src/content</code> directory is strictly reserved for content collections. Don’t use this directory for anything else.</p>
<p>Now that we know what a content collection is, the individual documents or entries within a collection are referred to as collection entries.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/collection_entries.png" alt="Collection entries within a single collection" width="643" height="371" loading="lazy">
<em>Collection entries within a single collection</em></p>
<p>Collection entries are documents in formats such as Markdown or MDX. They can also be in data formats such as JSON or YAML. For consistency, you’ll find most collection entries with a consistent naming pattern, for example kebab-case.</p>
<h3 id="heading-what-problems-do-content-collections-solve">What problems do content collections solve?</h3>
<p>Littering a project with different content documents and no clear structure is a surefire way to create a mess.</p>
<p>The better solution: use content collections.</p>
<p>Now, content collections aim to address three main problems:</p>
<ol>
<li>Organising documents.</li>
<li>Validating the document structure (for example validating the frontmatter properties of a markdown file).</li>
<li>Providing strong type safety while querying and working with content collections.</li>
</ol>
<h3 id="heading-how-to-organize-content-collections">How to organize content collections</h3>
<p>When working with content collections, note that only top-level directories in <code>src/content</code> count as collections. </p>
<p>For example, with multiple collections such as <code>blogs</code>, <code>authors</code> and <code>comments</code>, we could accurately represent these distinct content types with three top-level directories within <code>src/content</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/content_collection_example.png" alt="Organising different content collections " width="256" height="289" loading="lazy">
<em>Organising different content collections</em></p>
<p>If there’s a need to further organise content via subdirectories within a collection, that’s entirely acceptable! For example, the <code>blogs</code> content collection may have subdirectories to organise content via languages for example <code>en</code>, <code>fr</code>, and so on.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/collection_subdirectories.png" alt="Subdirectories within content collections" width="256" height="342" loading="lazy">
<em>Subdirectories within content collections</em></p>
<h3 id="heading-how-to-authorize-content-with-mdx">How to authorize content with MDX</h3>
<p>Take a look at the existing content collection in the project.</p>
<p>What do you see?</p>
<p>You should find a <code>blog</code> collection in <code>src/content/blog</code> with a handful of <code>.mdx</code> files.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-11-at-06.44.39.png" alt="Entries in the blog collection" width="663" height="260" loading="lazy">
<em>Entries in the blog collection</em></p>
<p>Each <code>mdx</code> file refers to the collection entry for the blog collection. But what is an <code>mdx</code> file?</p>
<p>MDX touts itself as the markdown for the component era. Think, what if we could use components in markdown? Well, with <code>MDX</code>, we can.</p>
<p>In these files, we can import components and embed them within our standard markdown content.</p>
<p>In the installation section of this chapter, we installed the Astro MDX plugin by running <code>npx astro add mdx</code>.</p>
<p>It’s about time we got started utilising MDX.</p>
<h3 id="heading-how-to-configure-content-collections">How to configure content collections</h3>
<p>A big part of content collections is ensuring a consistent collection entry format for every content collection.</p>
<p>For example, assuming a number markdown or MDX collection entries, we can go ahead and ensure that every collection entry has the same frontmatter properties. As you can imagine, this protects the integrity of each collection entry and breeds confidence that no surprising bug will spring at us when working with the entries.</p>
<p>So, how do we ensure such consistency?</p>
<p>The way we do this is by creating collection schemas.</p>
<p>A schema enforces consistent collection entry data within a collection. This is also what powers the TypeScript support we’ll get when working with the collection entries.</p>
<p>To create our collection schema, go ahead and create a <code>src/content/config.ts</code> file with the following content:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Import utilities from astro:content</span>
<span class="hljs-keyword">import</span> { z, defineCollection } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro:content"</span>;

<span class="hljs-comment">// Define the type and schema for one or more collections</span>
<span class="hljs-keyword">const</span> blogCollection = defineCollection({
  <span class="hljs-attr">type</span>: <span class="hljs-string">'content'</span>,
  <span class="hljs-comment">// an object of strings - title, year, month, day, and intro</span>
  <span class="hljs-attr">schema</span>: z.object({
    <span class="hljs-attr">title</span>: z.string(),
    <span class="hljs-attr">year</span>: z.string(),
    <span class="hljs-attr">month</span>: z.string(),
    <span class="hljs-attr">day</span>: z.string(),
    <span class="hljs-attr">intro</span>: z.string(),
  }),
});

<span class="hljs-comment">// Export a single collections object to register the collections </span>
<span class="hljs-comment">// The key should match the collection directory name in "src/content"</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> collections = {
  <span class="hljs-attr">blog</span>: blogCollection, <span class="hljs-comment">// add the blog collection </span>
};
</code></pre>
<p>Take a look at the annotated code above.</p>
<p>You don’t need to memorise how to do this, as you can always refer to the official documentation. But remember that the schema for a project’s content collections is defined in a <code>src/content/config.ts</code> (or <code>.js</code> and <code>.mjs</code>) file.</p>
<p>If we break down what goes on in a collection configuration file, we have three main actions:</p>
<ol>
<li>Import utilities from <code>astro:content</code>.</li>
<li>Define the content collection(s) schema via the <code>z</code> utility.</li>
<li>Export a single object of collection name key and schema value.</li>
</ol>
<p>The schema is the brain behind guaranteeing our content contains the right data and also provides TypeScript support — autocompletion and type-checking when querying the collection.</p>
<p>I know the question you’re likely asking.</p>
<p>What’s the <code>z</code> utility exported from <code>astro:content</code>?</p>
<p>The <code>z</code> utility re-exports the widely popular <a target="_blank" href="https://github.com/colinhacks/zod">zod</a> library — a TypeScript-first schema validation library with static type inference. The <code>z</code> variable in the <code>config</code> is a convenient export from <code>zod</code>.</p>
<h4 id="heading-quick-intro-to-zod">Quick intro to Zod</h4>
<p>While this is not a Zod book, the truth remains that if we will be defining schemas with Zod, it pays to understand the basics.</p>
<p>So, here’s a quick intro.</p>
<p>First, consider the schema for our <code>blog</code> collection:</p>
<pre><code class="lang-js">z.object({
  <span class="hljs-attr">title</span>: z.string(),
  <span class="hljs-attr">year</span>: z.string(),
  <span class="hljs-attr">month</span>: z.string(),
  <span class="hljs-attr">day</span>: z.string(),
  <span class="hljs-attr">intro</span>: z.string(),
})
</code></pre>
<p>Let’s deconstruct this.</p>
<p>Creating a schema starts with importing Zod. With, Astro that’s done via the import from <code>astro:content</code></p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> {z} <span class="hljs-keyword">from</span> <span class="hljs-string">'astro:content'</span>
</code></pre>
<p>To create a schema for a string property, use the <code>string</code> method as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> stringSchema = z.string()
</code></pre>
<p>To create an object schema, you guessed right. We use the <code>object</code> method as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myObjectSchema = z.object({

})
</code></pre>
<p>Now, within this object, we may define properties as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> myObjectSchema = z.object({
    <span class="hljs-attr">someString</span>: z.string()
})
</code></pre>
<p>In our blog collection schema, we’re essentially saying that the markdown (and MDX) files within the <code>blog</code> collection must have string front matter properties of <code>title</code>, <code>year</code>, <code>month</code>, <code>day</code> and <code>intro</code>.</p>
<p>The frontmatter is represented by the object schema and its properties, the object keys.</p>
<p>Now, go ahead and view all the collection entries in the <code>blog</code> collection and note how they all have defined properties.</p>
<h4 id="heading-the-astro-folder">The <code>.astro</code> folder</h4>
<p>As you create and work with content collections, Astro creates a <code>.astro</code> directory in the root of our project to keep track of important metadata for our content collections — mostly generated type information.</p>
<p>It’s safe to ignore this directory.</p>
<p>The <code>.astro</code> directory is updated automatically as we run <code>astro dev</code> or <code>astro build</code> commands. But if we find the type information not in sync, we can manually run <code>astro sync</code> at any time to update the <code>.astro</code> directory manually.</p>
<h2 id="heading-how-to-query-and-render-content-collections">How to Query and Render Content Collections</h2>
<p>So, we know how to create content collections and define their schemas. What next?</p>
<p>Content collections exist to be consumed in some way — typically by querying and rendering the collections.</p>
<p>So, how do we get started with this?</p>
<p>A collection consists of one or more collection entries. So, to query an entire collection, Astro provides the <code>getCollection()</code> method.</p>
<p>Consider how we may fetch all blog posts in our project:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> { getCollection } <span class="hljs-keyword">from</span> <span class="hljs-string">'astro:content'</span>

<span class="hljs-comment">// Get all entries from the blog collection </span>
<span class="hljs-keyword">const</span> allBlogPosts = <span class="hljs-keyword">await</span> getCollection(<span class="hljs-string">'blog'</span>)
---
</code></pre>
<p>To filter the collection entries, we may pass a second function argument to <code>getCollection</code> as shown below:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> { getCollection } <span class="hljs-keyword">from</span> <span class="hljs-string">'astro:content'</span>

<span class="hljs-comment">// Get all entries from the blog collection </span>
<span class="hljs-keyword">const</span> allBlogPosts = <span class="hljs-keyword">await</span> getCollection(<span class="hljs-string">'blog'</span>, <span class="hljs-function">(<span class="hljs-params">{data}</span>) =&gt;</span> {
  <span class="hljs-comment">// return only blogs from a certain year</span>
  <span class="hljs-keyword">return</span> data.year === <span class="hljs-string">'2023'</span>
})
---
</code></pre>
<p>Note that in our case, the <code>data</code> above refers to the frontmatter properties of our <code>MDX</code> blog entries.</p>
<p>How about getting a single collection entry?</p>
<p>Your first inclination may be to filter as shown below:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> { getCollection } <span class="hljs-keyword">from</span> <span class="hljs-string">'astro:content'</span>

<span class="hljs-comment">// Get all entries from the blog collection </span>
<span class="hljs-keyword">const</span> allBlogPosts = <span class="hljs-keyword">await</span> getCollection(<span class="hljs-string">'blog'</span>, <span class="hljs-function">(<span class="hljs-params">{data}</span>) =&gt;</span> {
  <span class="hljs-comment">// return only a specific title</span>
  <span class="hljs-keyword">return</span> data.title === <span class="hljs-string">'my-single-blog-title"
})
---</span>
</code></pre>
<p>The above is technically valid. But Astro provides a <code>getEntry()</code> method specifically for this case.</p>
<p>Consider the usage below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> {getEntry} <span class="hljs-keyword">from</span> <span class="hljs-string">'astro:content'</span>

<span class="hljs-comment">// Get a single blog entry with the entry slug </span>
<span class="hljs-keyword">const</span> blog = <span class="hljs-keyword">await</span> getEntry(<span class="hljs-string">'blog'</span>, <span class="hljs-string">'introduction-to-react'</span>)
</code></pre>
<p>The example above will fetch the entry in the <code>src/content/blog/introduction-to-react.mdx</code> route.</p>
<p>Note that both <code>getCollection</code> and <code>getEntry</code> return a <a target="_blank" href="https://docs.astro.build/en/reference/api-reference/#collection-entry-type">CollectionEntry</a> type.</p>
<p>Enough with the theory, let’s get back to building our project.</p>
<p>Find the next TODO on the <code>blog/index.astro</code> page:</p>
<pre><code class="lang-js">📂 src/pages/blog/index.astro

&lt;!-- ❗️TODO: List and render (all) blog post cards --&gt;
</code></pre>
<p>The goal is to fetch all the blogs in the blog content collection and render visual cards for each entry. Also, note that clicking each card should point to the actual blog.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-10-at-05.49.23.png" alt="Rendering blog post cards. " width="1194" height="854" loading="lazy">
<em>Rendering blog post cards.</em></p>
<p>Consider the solution below:</p>
<pre><code class="lang-js">📂 src/pages/blog/index.astro

---
<span class="hljs-comment">// Import getCollection from astro:content </span>
<span class="hljs-keyword">import</span> { getCollection } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro:content"</span>;
<span class="hljs-comment">// Import the BlogCard visual component </span>
<span class="hljs-keyword">import</span> BlogCard <span class="hljs-keyword">from</span> <span class="hljs-string">"@components/BlogCard.astro"</span>;
<span class="hljs-comment">// Import the getMonthName utility </span>
<span class="hljs-keyword">import</span> { getMonthName } <span class="hljs-keyword">from</span> <span class="hljs-string">"@utils/getMonthName"</span>;

<span class="hljs-comment">// Fetch all the blog posts </span>
<span class="hljs-keyword">const</span> allBlogPosts = <span class="hljs-keyword">await</span> getCollection(<span class="hljs-string">"blog"</span>);
---

{<span class="hljs-comment">/** render all blog posts **/</span>}
  &lt;div <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"mt-12 flex flex-col gap-5 px-5 sm:-mx-5 lg:px-4"</span>&gt;
    {
      allBlogPosts.map(<span class="hljs-function">(<span class="hljs-params">{ data, slug }</span>) =&gt;</span> {
        <span class="hljs-keyword">const</span> url = <span class="hljs-string">`/blog/<span class="hljs-subst">${data.year}</span>/<span class="hljs-subst">${data.month}</span>/<span class="hljs-subst">${data.day}</span>/<span class="hljs-subst">${slug}</span>`</span>;

        <span class="hljs-keyword">return</span> (
          <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BlogCard</span>
            <span class="hljs-attr">url</span>=<span class="hljs-string">{url}</span>
            <span class="hljs-attr">date</span>=<span class="hljs-string">{</span>`${<span class="hljs-attr">getMonthName</span>(+<span class="hljs-attr">data.month</span>)} ${<span class="hljs-attr">data.day</span>}, ${<span class="hljs-attr">data.year</span>}`}
            <span class="hljs-attr">title</span>=<span class="hljs-string">{data.title}</span>
          &gt;</span>
            {data.intro}
          <span class="hljs-tag">&lt;/<span class="hljs-name">BlogCard</span>&gt;</span></span>
        );
      })
    }
  &lt;/div&gt;
</code></pre>
<p>Note the URL of each blog constructed in the solution above:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> url = <span class="hljs-string">`/blog/<span class="hljs-subst">${data.year}</span>/<span class="hljs-subst">${data.month}</span>/<span class="hljs-subst">${data.day}</span>/<span class="hljs-subst">${slug}</span>`</span>;
</code></pre>
<p>For example, the blog collection entry <code>data-fetching-with-react-server-components.mdx</code> will have the path: <code>/blog/2020/12/21/data-fetching-with-react-server-components</code>.</p>
<p>Go ahead and click any of the blog cards. At the moment, they should lead to an empty page.</p>
<p>Let’s resolve that.</p>
<h2 id="heading-dynamic-routing">Dynamic Routing</h2>
<p>Static routes are arguably easy to reason about. For example, <code>.astro</code>, <code>.md</code> and <code>.mdx</code> files in <code>src/pages</code> will automatically become pages on our website.</p>
<p>But sometimes we require dynamic routes to prevent repetition. This typically happens when we have different routes with minimal UI changes between them.</p>
<p>For example, consider our current project. The blogs will have different routes, but each blog’s look and feel are identical.</p>
<pre><code class="lang-ts"><span class="hljs-comment">// example routes for different blogs </span>
/blog/<span class="hljs-number">2020</span>/<span class="hljs-number">12</span>/<span class="hljs-number">21</span>/data-fetching-<span class="hljs-keyword">with</span>-react-server-components
/blog/<span class="hljs-number">2023</span>/<span class="hljs-number">04</span>/<span class="hljs-number">24</span>/some-other-blog-title
/blog/<span class="hljs-number">2023</span>/<span class="hljs-number">07</span>/<span class="hljs-number">12</span>/getting-started-<span class="hljs-keyword">with</span>-react
</code></pre>
<pre><code class="lang-ts"><span class="hljs-comment">// 👀 Manually creating multiple pages for each blog </span>
/pages/<span class="hljs-number">2020</span>/<span class="hljs-number">12</span>/<span class="hljs-number">21</span>/data-fetching-<span class="hljs-keyword">with</span>-react-server-components.astro
/pages/<span class="hljs-number">2023</span>/<span class="hljs-number">04</span>/<span class="hljs-number">24</span>/some-other-blog-title.astro
/pages/<span class="hljs-number">2023</span>/<span class="hljs-number">07</span>/<span class="hljs-number">12</span>/getting-started-<span class="hljs-keyword">with</span>-react.astro
</code></pre>
<p>Manually providing multiple pages for each blog is arguably tedious.</p>
<p>Instead of manually creating different pages to represent each blog, we may dynamically handle the routing in one of two ways.</p>
<h3 id="heading-1-named-parameters">1. Named parameters</h3>
<p>The URL structure of the blogs could be represented by <code>/${year}/${month}/${day}/${title}</code> where <code>title</code> represents the blog’s title and <code>year</code>, <code>month</code> and <code>day</code>, describe when the blog was published.</p>
<p>We could represent the variables in the route path with named parameters surrounded by square brackets.</p>
<p>For example, we can create a file in the <code>pages/blog</code> directory with the following file name:</p>
<pre><code class="lang-md">/[year]/[month]/[day]/[title].astro
</code></pre>
<p>Since our pages are statically built, for example when we run the build script, all the routes must be determined at build time.</p>
<p>To achieve this, we must export a <code>getStaticPaths</code> function that returns an array of objects that correspond to each route. Here’s how:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 pages/blog/[year]/[month]/[day]/[title].astro</span>
---
<span class="hljs-keyword">import</span> BlogLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"@layouts/BlogLayout.astro"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticPaths</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> [
        {
            <span class="hljs-attr">params</span>: {
                <span class="hljs-attr">title</span>: <span class="hljs-string">"data-fetching-with-react-server-components"</span>,
                <span class="hljs-attr">year</span>: <span class="hljs-string">"2020"</span>,
                <span class="hljs-attr">month</span>: <span class="hljs-string">"12"</span>,
                <span class="hljs-attr">day</span>: <span class="hljs-string">"21"</span>,
            },
        },
    ];
}
---
</code></pre>
<p>Note that <code>getStaticPaths</code> specifically returns an object with a <code>params</code> field that defines all the variables in the route path that is <code>title</code>, <code>year</code>, <code>month</code> and <code>day</code></p>
<p>To add another blog route, simply add another object with its <code>params</code> property:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 pages/blog/[year]/[month]/[day]/[title].astro</span>
---
<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticPaths</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> [
        {
            <span class="hljs-attr">params</span>: {
                <span class="hljs-attr">title</span>: <span class="hljs-string">"data-fetching-with-react-server-components"</span>,
                <span class="hljs-attr">year</span>: <span class="hljs-string">"2020"</span>,
                <span class="hljs-attr">month</span>: <span class="hljs-string">"12"</span>,
                <span class="hljs-attr">day</span>: <span class="hljs-string">"21"</span>,
            },
        },
        {
            <span class="hljs-attr">params</span>: {
                <span class="hljs-attr">title</span>: <span class="hljs-string">"introducing-react-dev"</span>,
                <span class="hljs-attr">year</span>: <span class="hljs-string">"2023"</span>,
                <span class="hljs-attr">month</span>: <span class="hljs-string">"03"</span>,
                <span class="hljs-attr">day</span>: <span class="hljs-string">"16"</span>,
            },
        },
    ];
}
---
</code></pre>
<p>With the route <code>params</code> defined, we then grab the variables and render each blog as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 pages/blog/[year]/[month]/[day]/[title].astro</span>
---
<span class="hljs-keyword">import</span> BlogLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"@layouts/BlogLayout.astro"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticPaths</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> [
        {
            <span class="hljs-attr">params</span>: {
                <span class="hljs-attr">title</span>: <span class="hljs-string">"data-fetching-with-react-server-components"</span>,
                <span class="hljs-attr">year</span>: <span class="hljs-string">"2020"</span>,
                <span class="hljs-attr">month</span>: <span class="hljs-string">"12"</span>,
                <span class="hljs-attr">day</span>: <span class="hljs-string">"21"</span>,
            },
        },
        {
            <span class="hljs-attr">params</span>: {
                <span class="hljs-attr">title</span>: <span class="hljs-string">"introducing-react-dev"</span>,
                <span class="hljs-attr">year</span>: <span class="hljs-string">"2023"</span>,
                <span class="hljs-attr">month</span>: <span class="hljs-string">"03"</span>,
                <span class="hljs-attr">day</span>: <span class="hljs-string">"16"</span>,
            },
        },
    ];
}

<span class="hljs-comment">// Get the path variables from Astro.params</span>
<span class="hljs-keyword">const</span> { title, year, month, day } = Astro.params;
---

<span class="hljs-comment">// Provide markup for each matched page </span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BlogLayout</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"React Blog - React"</span> <span class="hljs-attr">header</span>=<span class="hljs-string">"React Blog"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{year}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{month}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{day}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">BlogLayout</span>&gt;</span></span>
</code></pre>
<p>Clicking on the <em>data fetching with react server components</em> and <em>introducing react dev blog</em> cards should now render their accompanying page.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-02-at-07.41.17.png" alt="Rendered blog markup" width="1441" height="878" loading="lazy">
<em>Rendered blog markup</em></p>
<h3 id="heading-2-rest-parameters">2. Rest parameters</h3>
<p>Rest parameters provide ultimate flexibility in our URL routing. For example, we may use <code>[...path]</code> to match file paths <strong>of any depth</strong>. Where <code>path</code> could be represented by any string, for example <code>[...file]</code> or <code>[...somestring]</code>.</p>
<p>Following our existing example, how may we reduce the path <code>pages/blog/[year]/[month]/[day]/[title].astro</code> to simply <code>pages/blog/[...path].astro</code>.</p>
<p>Delete the previous directories and file that made up <code>[year]/[month]/[day]/[title].astro</code> and create a single <code>blog/[...path].astro</code>.</p>
<p>This new file will match the blog route.</p>
<p>Similarly, we need to provide a <code>getStaticPaths</code> function, but the variable to be provided here is <code>path</code> as shown below:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> BlogLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"@layouts/BlogLayout.astro"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticPaths</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">return</span> [
        {
            <span class="hljs-attr">params</span>: {
                <span class="hljs-attr">path</span>: <span class="hljs-string">"2020/12/21/data-fetching-with-react-server-components"</span>,
            },
        },
        {
            <span class="hljs-attr">params</span>: {
                <span class="hljs-attr">path</span>: <span class="hljs-string">"2023/03/16/introducing-react-dev"</span>,
            },
        },
    ];
}

<span class="hljs-keyword">const</span> { path } = Astro.params;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BlogLayout</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"React Blog - React"</span> <span class="hljs-attr">header</span>=<span class="hljs-string">"React Blog"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{path}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">BlogLayout</span>&gt;</span></span>
</code></pre>
<p>Clicking on the <em>data fetching with react server components</em> and <em>introducing react dev blog</em> cards should now render their accompanying page.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-02-at-07.40.03.png" alt="Rendered blog markup" width="1431" height="861" loading="lazy">
<em>Rendered blog markup</em></p>
<h3 id="heading-priority-order">Priority order</h3>
<p>As we’ve discussed, URL paths can be matched in different ways. So what happens when different file paths match the same URL path in our project?</p>
<p>Well, Astro needs to make a decision, and that’s following the priority list below:</p>
<ol>
<li>Static routes, that is those without path parameters, have the highest priority, for example <code>/pages/products/this-is-a-product</code>.</li>
<li>Dynamic routes with named parameters have the next priority, for example <code>/pages/products/[id]</code>.</li>
<li>Dynamic routes with rest parameters have the lowest priority, for example <code>/pages/products/[...path]</code>.</li>
<li>Following the above, any ties will be resolved alphabetically.</li>
</ol>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/route_priority.png" alt="Route priority order from first to last." width="2138" height="735" loading="lazy">
<em>Route priority order from first to last.</em></p>
<p>A decent example is to note that even though the dynamic path <code>[...path.astro]</code> matches the root path <code>/blog</code>, the static route <code>blog/index.astro</code> always takes priority while the dynamic route <code>[...path.astro]</code> kicks in for each blog page.</p>
<h2 id="heading-how-to-generate-routes-with-content-collections">How to Generate Routes with Content Collections</h2>
<p>Right now, we’re manually adding objects to the exported <code>getStaticPaths</code> function to define our blog paths.</p>
<p>But our desired solution is to generate these from the blog content collection.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/auto_entry_route.png" alt="Automatically generate routes for 
each collection entry" width="707" height="326" loading="lazy">
<em>Automatically generate routes for each collection entry</em></p>
<p>To achieve this, we need to rework the <code>getStaticPaths</code> implementation to fetch all blog posts from the content collection and generate the required paths.</p>
<p>Consider the solution below:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> { getCollection } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro:content"</span>;
<span class="hljs-keyword">import</span> BlogLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"@layouts/BlogLayout.astro"</span>;

<span class="hljs-comment">// Make the function async</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticPaths</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-comment">// Fetch all blog posts </span>
    <span class="hljs-keyword">const</span> allBlogPosts = <span class="hljs-keyword">await</span> getCollection(<span class="hljs-string">"blog"</span>);
    <span class="hljs-comment">// Dynamically construct the blog paths</span>
    <span class="hljs-keyword">const</span> paths = allBlogPosts.map(<span class="hljs-function">(<span class="hljs-params">blogEntry</span>) =&gt;</span> ({
        <span class="hljs-comment">// construct params</span>
        <span class="hljs-attr">params</span>: {
            <span class="hljs-attr">path</span>: <span class="hljs-string">`<span class="hljs-subst">${blogEntry.data.year}</span>/<span class="hljs-subst">${blogEntry.data.month}</span>/<span class="hljs-subst">${blogEntry.data.day}</span>/<span class="hljs-subst">${blogEntry.slug}</span>`</span>,
        },
    }));

    <span class="hljs-comment">// Eventually return the constructed paths</span>
    <span class="hljs-keyword">return</span> paths;
}

<span class="hljs-keyword">const</span> { path } = Astro.params;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BlogLayout</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"React Blog - React"</span> <span class="hljs-attr">header</span>=<span class="hljs-string">"React Blog"</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{path}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">BlogLayout</span>&gt;</span></span>
</code></pre>
<p>Now, every single blog entry now has an associating path defined. Give this a try by clicking any blog link from the home page.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-02-at-07.51.47.png" alt="All blog paths now automatically handled " width="1416" height="965" loading="lazy">
<em>All blog paths now automatically handled</em></p>
<h3 id="heading-how-to-render-each-blog-content">How to render each blog content</h3>
<p>Just rendering the path of the blog was great for simplifying the previous concepts, but that’s not quite our result.</p>
<p>Let’s properly render each blog content. First here’s the solution:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> { getCollection } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro:content"</span>;
<span class="hljs-keyword">import</span> BlogLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"@layouts/BlogLayout.astro"</span>;

<span class="hljs-comment">// Make the function async</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">async</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">getStaticPaths</span>(<span class="hljs-params"></span>) </span>{
    <span class="hljs-keyword">const</span> allBlogPosts = <span class="hljs-keyword">await</span> getCollection(<span class="hljs-string">"blog"</span>);
    <span class="hljs-comment">// dynamically construct the blog paths</span>
    <span class="hljs-keyword">const</span> paths = allBlogPosts.map(<span class="hljs-function">(<span class="hljs-params">blogEntry</span>) =&gt;</span> ({
        <span class="hljs-comment">// construct params</span>
        <span class="hljs-attr">params</span>: {
            <span class="hljs-attr">path</span>: <span class="hljs-string">`<span class="hljs-subst">${blogEntry.data.year}</span>/<span class="hljs-subst">${blogEntry.data.month}</span>/<span class="hljs-subst">${blogEntry.data.day}</span>/<span class="hljs-subst">${blogEntry.slug}</span>`</span>,
        },
        <span class="hljs-comment">// 👀 Pass blogEntry as props to be later accessed in the markup via Astro.props</span>
        <span class="hljs-attr">props</span>: {
            blogEntry,
        },
    }));

    <span class="hljs-comment">//Eventually return the constructed paths</span>
    <span class="hljs-keyword">return</span> paths;
}

<span class="hljs-comment">// Get the blog entry from the props</span>
<span class="hljs-keyword">const</span> { blogEntry } = Astro.props;

<span class="hljs-comment">// get blog content via entry.render()</span>
<span class="hljs-keyword">const</span> { Content } = <span class="hljs-keyword">await</span> blogEntry.render();
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BlogLayout</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"React Blog - React"</span> <span class="hljs-attr">header</span>=<span class="hljs-string">"React Blog"</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Render the Content --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">BlogLayout</span>&gt;</span></span>
</code></pre>
<p>Let’s deconstruct this solution.</p>
<p>The most important piece to the solution puzzle is passing every single blog entry as a <code>prop</code> in the <code>getStaticPath</code> function.</p>
<p>Doing this allows us to reference each entry in the component markup section via <code>Astro.props</code>.</p>
<p>Secondly, every queried collection entry has a <code>render()</code> method that renders the entry to <code>HTML</code>. The solution utilises this to render each blog.</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { Content } = <span class="hljs-keyword">await</span> blogEntry.render();
<span class="hljs-comment">//...</span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">Content</span> /&gt;</span></span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-02-at-08.48.36.png" alt="The rendered blog content" width="1461" height="884" loading="lazy">
<em>The rendered blog content</em></p>
<h2 id="heading-mdx-components">MDX Components</h2>
<p>Let’s get back to MDX.</p>
<p>The most impressive feature of MDX is the ability to use components with standard markdown content.</p>
<p>Let’s consider practical examples.</p>
<h3 id="heading-customised-html-elements">Customised HTML elements</h3>
<p>When MDX content is rendered to HTML, the eventual output uses standard HTML elements.</p>
<p>For example, if we had the following MDX content:</p>
<pre><code class="lang-js"># Title 

This is a paragraph
</code></pre>
<p>This will yield an HTML result similar to the following:</p>
<pre><code class="lang-js">&lt;h1&gt;Title&lt;/h1&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>This is a paragraph<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span></span>
</code></pre>
<p>The good news is, instead of relying on standard HTML elements, we can specific components to be used instead of HTML elements. </p>
<p>For example, we may provide our own styled header and paragraph components in place of the standard <code>h1</code> and <code>p</code> HTML elements.</p>
<p>To do this, create an object of HTML element to custom component mapping.</p>
<pre><code class="lang-js"><span class="hljs-comment">// sample MDX component map </span>

<span class="hljs-comment">// Provide custom header and paragraph</span>
<span class="hljs-keyword">import</span> H1 <span class="hljs-keyword">from</span> <span class="hljs-string">"./H1.astro"</span>; <span class="hljs-comment">// custom Astro component</span>
<span class="hljs-keyword">import</span> P <span class="hljs-keyword">from</span> <span class="hljs-string">"./P.astro"</span> <span class="hljs-comment">// custom paragraph component</span>

<span class="hljs-comment">// map of HTML element to custom component</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> mdxComponents = {
  <span class="hljs-attr">h1</span>: H1,
  <span class="hljs-attr">p</span>: P,
}
</code></pre>
<p>Now, when the MDX content is rendered to HTML, pass the component map as shown below:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> {getEntry} <span class="hljs-keyword">from</span> <span class="hljs-string">'astro:content'</span>
<span class="hljs-comment">// import the component map </span>
<span class="hljs-keyword">import</span> { mdxComponents } <span class="hljs-keyword">from</span> <span class="hljs-string">'../mdxComponents'</span>

<span class="hljs-comment">// Get a collection entry</span>
<span class="hljs-keyword">const</span> blogCollection = <span class="hljs-keyword">await</span> getEntry(<span class="hljs-string">'blog'</span>, <span class="hljs-string">'some-title'</span>)
<span class="hljs-comment">// Get the entry Content</span>
<span class="hljs-keyword">const</span> { Content } = <span class="hljs-keyword">await</span> blogEntry.render();
---

{<span class="hljs-comment">/** Render to HTML and pass the components map**/</span>}
&lt;Content components={mdxComponents} /&gt;
</code></pre>
<p>Let’s put this into action.</p>
<p>Take a look at the <code>src/components/mdxComponents.ts</code> file in the project. It contains a list of HTML elements and associated custom Astro components.</p>
<p>We’ll import this object and pass it to the blog entry <code>&lt;Content /&gt;</code> as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 pages/blog/[...path].astro</span>
---
<span class="hljs-keyword">import</span> { mdxComponents } <span class="hljs-keyword">from</span> <span class="hljs-string">"@components/mdxComponents"</span>;
<span class="hljs-comment">// ... other imports </span>
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BlogLayout</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"React Blog - React"</span> <span class="hljs-attr">header</span>=<span class="hljs-string">"React Blog"</span>&gt;</span>
    {/** 👀 pass the components down to Content **/}
    <span class="hljs-tag">&lt;<span class="hljs-name">Content</span> <span class="hljs-attr">components</span>=<span class="hljs-string">{mdxComponents}</span> /&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">BlogLayout</span>&gt;</span></span>
</code></pre>
<p>With this, we should now have properly styled components in place of the bland HTML elements.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-10-at-06.39.24.png" alt="Leveraging custom components for the MDX HTML output" width="1128" height="810" loading="lazy">
<em>Leveraging custom components for the MDX HTML output</em></p>
<p>Consider the full list of available HTML elements that can be overwritten with custom components in the <a target="_blank" href="https://www.freecodecamp.org/news/p/3c1efa5a-f575-4365-9958-d220b339bc38/[https://mdxjs.com/table-of-components/]">official MDX documentation</a>.</p>
<h3 id="heading-internal-components">Internal components</h3>
<p>Components can also be imported and directly rendered within MDX. That’s part of the fun!</p>
<p>Go ahead and open the first blog route in <code>/blog/2020/12/21/data-fetching-with-react-server-components</code> and find the first <code>TODO</code> on the page.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-10-at-06.42.47.png" alt="TODO: add the Intro component" width="1283" height="413" loading="lazy">
<em>TODO: add the Intro component</em></p>
<p>To resolve this TODO, we need to import and render the <code>Intro</code> component in <code>src/components/Intro.astro</code>.</p>
<p>Consider the solution below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/content/blog/data-fetching-with-react-server-components.mdx</span>
---

<span class="hljs-keyword">import</span> Intro <span class="hljs-keyword">from</span> <span class="hljs-string">"@components/Intro.astro"</span>;

{<span class="hljs-comment">/** First content after the frontmatter and other imports**/</span>}
&lt;Intro&gt;
  <span class="hljs-number">2020</span> has been a long year. As it comes to an end we wanted to share a special
  Holiday Update on our research into zero-bundle-size **React Server
  Components**.
&lt;/Intro&gt;
---
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-02-at-09.07.29.png" alt="The rendered Intro component" width="1476" height="551" loading="lazy">
<em>The rendered Intro component</em></p>
<p>We imported and rendered an Astro component right in the MDX file. How amazing!</p>
<p>Note that the <code>---</code> syntax represents dividers (as seen in 1 and 2 above) and not code fences as used to define markdown frontmatter.</p>
<p>There’s no limit to how many components we can import and render in an MDX file. So, we can go further and render another component as shown below:</p>
<pre><code class="lang-js">{<span class="hljs-comment">/** Import the Note component **/</span>}
<span class="hljs-keyword">import</span> Note <span class="hljs-keyword">from</span> <span class="hljs-string">"@components/Note.astro"</span>;

{<span class="hljs-comment">/** Render at the bottom of the file **/</span>}
&lt;Note&gt;React Server Components are still <span class="hljs-keyword">in</span> research and development.&lt;/Note&gt;
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-02-at-10.43.07.png" alt="The rendered Note component" width="1272" height="521" loading="lazy">
<em>The rendered Note component</em></p>
<p>Note that, unlike JavaScript imports that must be at the top of the file, we can import components in an MDX file anywhere aside from the frontmatter section.</p>
<p>I typically prefer to keep the imports at the top of the document right after the frontmatter, but you may also colocate the imports close to where they are rendered. Both options work!</p>
<h3 id="heading-external-imports">External imports</h3>
<p>We’ve seen different imported components in our MDX documents. Luckily, it gets even more fun.</p>
<p>We can also import and render external components, for example from NPM in MDX.</p>
<p>Go ahead and install <code>astro-embed</code></p>
<pre><code>npm install astro-embed
</code></pre><p><code>astro-embed</code> lets us embed components such as Tweets and Youtube videos in an Astro project.</p>
<p>In the same blog in <code>/blog/2020/12/21/data-fetching-with-react-server-components</code> consider the next TODO:</p>
<pre><code class="lang-md"><span class="hljs-section">## Reference</span>

To introduce React Server Components, we have prepared a talk 
and a demo. If you want, you can check them out during the. 
holidays, or later when work picks back up in the new year.

❗️TODO: Add Youtube video embed here
</code></pre>
<p>To resolve this, go ahead and import the <code>Youtube</code> component from <code>astro-embed</code> and render the component with an <code>id</code> prop as shown below:</p>
<pre><code class="lang-md"><span class="hljs-section">## Reference</span>

To introduce React Server Components, we have prepared a talk and a demo. If you want, you can check them out during the holidays, or later when work picks back up in the new year.

import { YouTube } from "astro-embed";

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">YouTube</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"https://youtu.be/TQQPAU21ZUw"</span> /&gt;</span></span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-10-at-07.05.09.png" alt="The rendered Youtube component" width="1071" height="795" loading="lazy">
<em>The rendered Youtube component</em></p>
<p>Note that we’re colocating the import statement close to the component render. But we may move the import higher up the file as well.</p>
<pre><code class="lang-md">{/<span class="hljs-strong">** ✅ This is correct **</span>/}

import { YouTube } from "astro-embed";

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">YouTube</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"https://youtu.be/TQQPAU21ZUw"</span> /&gt;</span></span>
</code></pre>
<pre><code class="lang-md">{/<span class="hljs-strong">** ✅ This is equally correct **</span>/}

{/<span class="hljs-strong">** Keep all imports on top, right after the frontmatter **</span>/}

import Intro from "@components/Intro.astro";
import { YouTube } from "astro-embed";

{/<span class="hljs-strong">** Render other content ... and component much later **</span>/}

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">YouTube</span> <span class="hljs-attr">id</span>=<span class="hljs-string">"https://youtu.be/TQQPAU21ZUw"</span> /&gt;</span></span>
</code></pre>
<h3 id="heading-autoimport">AutoImport</h3>
<p>The <code>Youtube</code>, <code>Intro</code> and <code>Note</code> components are used across all the blogs. Right now, importing the components every single time seems repetitive.</p>
<p>With components we want to be reused across our entire MDX files, how about we automatically import these – that is, without manually duplicating the import in every MDX document?</p>
<p>To achieve this, we will leverage the <code>astro-auto-import</code> package.</p>
<p>With <code>astro-auto-import</code>, we can easily import components or modules automatically and utilize them in MDX files without the need for manual importing.</p>
<p>First, install <code>astro-auto-import</code>:</p>
<pre><code class="lang-md">npm install astro-auto-import
</code></pre>
<p><code>astro-auto-import</code> works as an Astro integration. To use it, we must update the project <code>astro.config.mjs</code> file as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// other imports ...</span>
<span class="hljs-comment">// import AutoImport</span>
<span class="hljs-keyword">import</span> AutoImport <span class="hljs-keyword">from</span> <span class="hljs-string">"astro-auto-import"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">integrations</span>: [
   <span class="hljs-comment">// Pass AutoImport in the integrations array </span>
    AutoImport({
      <span class="hljs-attr">imports</span>: [
        <span class="hljs-comment">/**
         * Generates:
         * import Intro from './src/components/Intro.astro';
         */</span>
        <span class="hljs-string">"./src/components/Intro.astro"</span>,
        <span class="hljs-string">"./src/components/Note.astro"</span>,
        <span class="hljs-comment">/**
         * Generates:
         * import { YouTube } from 'astro-embed';
         */</span>
        { <span class="hljs-string">"astro-embed"</span>: [<span class="hljs-string">"YouTube"</span>] },
      ],
    }),
    react(),
    tailwind(),
    mdx(),
  ],
});
</code></pre>
<p>To use <code>AutoImport</code> we pass it into the <code>integrations</code> array and invoke <code>AutoImport</code> with an imports list:</p>
<pre><code class="lang-js">AutoImport({
   <span class="hljs-attr">imports</span>: [
     <span class="hljs-string">"./src/components/Intro.astro"</span>,
     <span class="hljs-string">"./src/components/Note.astro"</span>,
     { <span class="hljs-string">"astro-embed"</span>: [<span class="hljs-string">"YouTube"</span>] },
   ],
})
</code></pre>
<p>The <code>imports</code> represents a list of imports to be automatically added to our MDX files.</p>
<p>A string with the path of the import such as <code>"./src/components/Intro.astro"</code> will generate a default import such as <code>import Intro from './src/components/Intro.astro'</code>.</p>
<p>An object such as <code>{ "astro-embed": ["YouTube"] }</code> generates a named import such as <code>import { Tweet, YouTube } from 'astro-embed'</code>.</p>
<p>With these in place, we must now remove the manual imports in the MDX files and rely on the <code>AutoImport</code> magic ✨</p>
<p>Neat!</p>
<h2 id="heading-integration-spotlight-astro-seo">Integration Spotlight: Astro SEO</h2>
<p>You’ve seen a lot of Astro integrations already. Think <code>@astrojs/react</code> for having React islands in an Astro project, or the official <code>@astrojs/tailwind</code> integration for using tailwind in Astro.</p>
<p>Generally speaking, integrations add new functionality and behaviour to an Astro project, usually with just a few lines of code.</p>
<p>Sounds like a win!</p>
<p>In this section, let’s discuss <code>astro-seo</code>, an integration that makes it straightforward to add SEO-relevant information to any Astro app.</p>
<p>You know the rodeo.</p>
<p>First, install the integration:</p>
<pre><code class="lang-js">npm install astro-seo
</code></pre>
<p>To use <code>astro-seo</code>, we import the <code>SEO</code> component and pass it relevant props as seen below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/BaseLayout.astro</span>
---
<span class="hljs-keyword">import</span> { SEO } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro-seo"</span>;
<span class="hljs-comment">// ...</span>
---
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>

    <span class="hljs-tag">&lt;<span class="hljs-name">SEO</span>
      <span class="hljs-attr">title</span>=<span class="hljs-string">{title}</span>
      <span class="hljs-attr">description</span>=<span class="hljs-string">{description}</span>
      <span class="hljs-attr">openGraph</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">basic:</span> {
          <span class="hljs-attr">title</span>,
          <span class="hljs-attr">type:</span> "<span class="hljs-attr">website</span>",
          <span class="hljs-attr">image:</span> "<span class="hljs-attr">https:</span>//<span class="hljs-attr">react.dev</span>/<span class="hljs-attr">images</span>/<span class="hljs-attr">og-home.png</span>",
        },
      }}
      <span class="hljs-attr">twitter</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">creator:</span> "@<span class="hljs-attr">reactjs</span>",
      }}
      <span class="hljs-attr">extend</span>=<span class="hljs-string">{{</span>
        <span class="hljs-attr">meta:</span> [
          {
            <span class="hljs-attr">name:</span> "<span class="hljs-attr">twitter:image</span>",
            <span class="hljs-attr">content:</span> "<span class="hljs-attr">https:</span>//<span class="hljs-attr">react.dev</span>/<span class="hljs-attr">images</span>/<span class="hljs-attr">og-home.png</span>",
          },
          { <span class="hljs-attr">name:</span> "<span class="hljs-attr">twitter:title</span>", <span class="hljs-attr">content:</span> "@<span class="hljs-attr">reactjs</span>" },
          {
            <span class="hljs-attr">name:</span> "<span class="hljs-attr">twitter:description</span>",
            <span class="hljs-attr">content:</span> <span class="hljs-attr">description</span>,
          },
        ],
      }}
    /&gt;</span>
  {/** ... **/}
<span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
{/** ... **/}
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>This will generate relevant meta tags including open-graph meta tags for a more SEO-compliant application.</p>
<h2 id="heading-how-to-create-custom-404-pages-in-astro">How to Create Custom 404 Pages in Astro</h2>
<p>Custom 404 pages are easy to reason about in Astro. Create a <code>404.astro</code> or any other relevant page file ending in <code>src/pages</code>. This will build a <code>404.html</code> page that most deployment services will use if an invalid page is requested and not found.</p>
<p>Let’s do this for our project.</p>
<p>Create a <code>404.astro</code> page in <code>src/pages</code> with the following content:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/404.astro</span>
---
<span class="hljs-keyword">import</span> BaseLayout <span class="hljs-keyword">from</span> <span class="hljs-string">"@layouts/BaseLayout.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">BaseLayout</span> <span class="hljs-attr">title</span>=<span class="hljs-string">"Redirecting ..."</span> <span class="hljs-attr">page</span>=<span class="hljs-string">"index"</span> /&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">script</span> <span class="hljs-attr">is:inline</span>&gt;</span><span class="javascript">
<span class="hljs-comment">// lazy redirect. This is better done server-side: discussed in the next book's chapter</span>
<span class="hljs-keyword">const</span> { pathname } = <span class="hljs-built_in">window</span>.location;

<span class="hljs-built_in">window</span>.location.replace(<span class="hljs-string">`https://www.react.dev<span class="hljs-subst">${pathname}</span>`</span>);
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span></span>
</code></pre>
<p>Our <code>404</code> page comes with a twist.</p>
<p>It renders a blank page via <code>&lt;BaseLayout /&gt;</code> and automatically redirects the user to the accompanying path on <code>www.react.dev</code>. Violà!</p>
<p>Give this a try by visiting the API reference link on the homepage.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/07/CleanShot-2023-07-10-at-07.28.40.png" alt="The API reference link" width="1073" height="536" loading="lazy">
<em>The API reference link</em></p>
<h2 id="heading-wrapping-up-this-chapter-4">Wrapping Up This Chapter</h2>
<p>Building rich content applications is right up Astro’s alley. With content collections, we can build large content-driven applications with organisation and confidence.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-138.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chapter six.</em></p>
<h1 id="heading-chapter-6-server-side-rendering-ssr-in-astro-1">Chapter 6: Server-Side Rendering (SSR) in Astro</h1>
<p>This chapter will show you how to enable SSR in an Astro project. We will also discuss a detailed overview of the extensive features a server-side rendered Astro project offers.</p>
<h2 id="heading-what-youll-learn-5">What You’ll Learn</h2>
<ul>
<li>Enable SSR in an Astro project.</li>
<li>Leverage environment variables to store secrets.</li>
<li>Provide flexible server routing via dynamic routes.</li>
<li>Understand the request-response cycle and its relevant properties.</li>
<li>Take advantage of Astro API routes to power robust applications.</li>
</ul>
<h2 id="heading-when-do-you-need-ssr">When Do You Need SSR?</h2>
<p>In an earlier chapter, we discussed several rendering techniques for a frontend application. The reason was so we could make effective decisions for when to choose one rendering technique over the other.</p>
<p>I’ll briefly summarise why we may need SSR in an Astro project. Remember that your mileage may vary – so always refer to the basics discussed in Chapter 3: Build Your Own Component Island.</p>
<p>Now, the following are pointers to when we may need to enable SSR in an Astro project:</p>
<ul>
<li><strong>Content that is subject to frequent changes.</strong>: We may need SSR if a page’s content frequently changes, rather than using a statically built page which would require a rebuild for every new change.</li>
<li><strong>The need for API endpoints</strong>: SSR allows us to create API endpoints while keeping sensitive data hidden from clients. We’ll see how to do this later in the chapter.</li>
<li><strong>Creating pages with restricted access</strong>: To limit access to a page, enable server rendering for server-side handling of user privileges.</li>
</ul>
<h2 id="heading-how-to-enable-ssr-in-astro">How to Enable SSR in Astro</h2>
<p>Okay, here’s how it all begins. To enable SSR in an Astro project, set the <code>output</code> configuration option to <code>server</code> in the <code>astro.config.mjs</code> file.</p>
<pre><code class="lang-ts"><span class="hljs-comment">// 📂 astro.config.mjs </span>

<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'astro/config'</span>


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-comment">//This will enable SSR</span>
  output: <span class="hljs-string">'server'</span>
})
</code></pre>
<p>And that’s it!</p>
<p>Let’s see this in action by starting a new project with the following command:</p>
<pre><code class="lang-ts">npm create astro<span class="hljs-meta">@latest</span> --  --template=minimal --yes --skip-houston ssr
</code></pre>
<p>This will use the <code>minimal</code> template, <code>--skip-houston</code> will skip the Houston animation, and the <code>--yes</code> option will skip all prompts and accept the defaults.</p>
<p>Now, change directories into <code>ssr</code> and start the project:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ssr &amp;&amp; npm start
</code></pre>
<p>The app should run on a local server with a single <code>index.astro</code> page.</p>
<p>If we build the application for production via <code>npm build</code>, we should have the single <code>index.astro</code> page pre-rendered, that is statically built.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-22-at-07.13.56.png" alt="Statically rendering the index.astro page." width="638" height="368" loading="lazy">
<em>Statically rendering the index.astro page.</em></p>
<p>To re-iterate, a pre-rendered application is essentially a static site, that is – not server-side rendered.</p>
<p>To initiate server-side rendering, let’s change the configuration to include the <code>output</code> property as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/astro.config.mjs</span>
<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'astro/config'</span>;

<span class="hljs-comment">// https://astro.build/config</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">output</span>: <span class="hljs-string">'server'</span>
});
</code></pre>
<p>If we rerun the production build, we will have an error in the console.</p>
<pre><code class="lang-she">[error] Cannot use `output: 'server'` without an adapter. Please install and configure the appropriate server adapter for your final deployment.
</code></pre>
<h2 id="heading-how-to-deploy-an-ssr-project">How to Deploy an SSR Project</h2>
<p>The root cause of the error above is that to build your application for server-side rendering, the Astro build command must know what server you’ll eventually be deploying to.</p>
<p>SSR requires a server runtime, that is the code running within the server that renders our Astro pages. To achieve this, Astro provides adapters that match our deployment runtime.</p>
<p>An adapter allows Astro to do two things. First, determine the server runtime environment. Second, output a script that runs the SSR code on the specified runtime.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/astro_adapter_needs.png" alt="The Astro adapter needs." width="2000" height="398" loading="lazy">
<em>The Astro adapter needs.</em></p>
<p>At the time of writing, the available Astro adapters are Cloudfare, Deno, Netlify, NodeJS, and Vercel.</p>
<p>We may deploy our SSR project to any of these runtimes with natively supported adapters.</p>
<p>To install any of these adapters, use the command:</p>
<pre><code class="lang-bash">npx astro add [name-of-adapter]
</code></pre>
<p><code>[name-of-adapter]</code> could be <code>cloudfare</code>, <code>deno</code>, <code>netlify</code>, <code>node</code> or <code>vercel</code>.</p>
<p>I recommend looking at the <a target="_blank" href="https://docs.astro.build/en/guides/deploy/">official reference</a> for any adapters you need in your project, as it would be unreasonable to cover all of these in the book. Here, we will stick to <code>netlify</code>.</p>
<p>To add the <code>netlify</code> adapter, go ahead and enter the following command in the terminal:</p>
<pre><code class="lang-bash">npx astro add netlify
</code></pre>
<p>This will go ahead and install the adapter and update our configuration file to the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/config"</span>;
<span class="hljs-comment">// 👀 look here</span>
<span class="hljs-keyword">import</span> netlify <span class="hljs-keyword">from</span> <span class="hljs-string">"@astrojs/netlify/functions"</span>;

<span class="hljs-comment">// https://astro.build/config</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">output</span>: <span class="hljs-string">"server"</span>,
  <span class="hljs-comment">// 👀 look here</span>
  <span class="hljs-attr">adapter</span>: netlify()
});
</code></pre>
<p>Essentially, the adapter is imported in the second line of the config and added to the <code>adapter</code> property.</p>
<p>Now re-run the build command:</p>
<pre><code class="lang-js">npm run build
</code></pre>
<p>This will successfully build our SSR project for production by outputting <code>netlify</code> specific code snippets in the <code>dist</code> and <code>.netlify</code> directory.</p>
<p>Now, we’re in business 🚀</p>
<h2 id="heading-use-the-correct-adapter">Use the Correct Adapter</h2>
<p>It goes without saying that, after adding an adapter, the project should be deployed to the specified adapter (here, <code>netlify</code>) and not some other provider (like <code>vercel</code>).</p>
<p>Use the correct adapter for your deployment runtime.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/adapter_deploy.png" alt="Deploying a Vercel adapter to Netlify is wrong." width="2000" height="805" loading="lazy">
<em>Deploying a Vercel adapter to Netlify is wrong.</em></p>
<p>Our actual deployment steps will vary depending on the server runtime being deployed. For example, for Netlify, we may follow the steps described in the deploy a static site in Chapter 1. These steps will be identical for similar runtimes like Vercel.</p>
<p>For other runtimes, the official Astro <a target="_blank" href="https://docs.astro.build/en/guides/deploy/">deployment guides</a> do an excellent job of explaining the deployment steps required.</p>
<h2 id="heading-ssr-with-static-pages">SSR with Static Pages</h2>
<p>With the <code>output</code> configuration property set to <code>server</code>, every page in our Astro project will be server-side rendered. But there’s a great chance we may want one or more pages to be statically generated at build time, that is some pages server-side rendered and others pre-rendered.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/hybrid_rendering.png" alt="Having a mix of server and statically rendered pages. " width="1582" height="1538" loading="lazy">
<em>Having a mix of server and statically rendered pages.</em></p>
<p>In such cases, we can opt-in to pre-rendering by adding <code>export const prerender = true</code> to any page that supports exporting variables, e.g., <code>.astro</code>, <code>.mdx</code> <code>, .ts</code> and <code>.js</code>.</p>
<p>Let’s try this out by creating a new <code>about.astro</code> page with the following content:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/about.astro </span>

---
<span class="hljs-comment">// 👀 note the prerender export</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> prerender = <span class="hljs-literal">true</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Astro<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>About us<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>With the <code>prerender</code> export, the <code>about</code> page will be statically rendered at build time, while the <code>index</code> page remains server-side rendered.</p>
<p>Run <code>npm run build</code> to see this in action.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-22-at-08.33.08.png" alt="Static and server-side generated pages in the same project." width="628" height="441" loading="lazy">
<em>Static and server-side generated pages in the same project.</em></p>
<h2 id="heading-from-request-to-response">From Request to Response</h2>
<p>The interaction between a client and server may be simplified in two steps:</p>
<ul>
<li>the client makes a <strong>request</strong>.</li>
<li>the server sends a <strong>response</strong>.</li>
</ul>
<p>The two main entities in this simplified interaction are the client request and the server response. Luckily, with server-side rendering, we may access details of the request and response object.</p>
<h3 id="heading-the-request-object">The Request object</h3>
<p>The <code>Request</code> object may be accessed on the <code>Astro</code> global as shown below:</p>
<pre><code class="lang-js">---
 <span class="hljs-keyword">const</span> request = Astro.request
---
</code></pre>
<p>The object holds information about the current request and is represented by the standard <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Request">Request</a> interface of the fetch API.</p>
<pre><code class="lang-js">interface Request <span class="hljs-keyword">extends</span> Body {
    readonly cache: RequestCache
    readonly credentials: RequestCredentials;
    readonly destination: RequestDestination;
    readonly headers: Headers;
    readonly integrity: string;
    readonly keepalive: boolean;
    readonly method: string;
    readonly mode: RequestMode;
    readonly redirect: RequestRedirect;
    readonly referrer: string;
    readonly referrerPolicy: ReferrerPolicy;
    readonly signal: AbortSignal;
    readonly url: string;
    clone(): Request;
}
</code></pre>
<p>For example, we may access the request headers via <code>Astro.request.headers</code> and the current request URL as a string via <code>Astro.request.url</code>.</p>
<h3 id="heading-the-response-object">The Response object</h3>
<p>The <code>Response</code> object is the corresponding interface representing the response to a request. This is also represented by the standard <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/Response">Response</a> interface of the Fetch API.</p>
<p>As opposed to accessing the object on the <code>Astro</code> object, the <code>Response</code> object is created using the <code>Response()</code> constructor.</p>
<p>The <code>Response()</code> constructor has the following signature:</p>
<pre><code class="lang-js"><span class="hljs-keyword">new</span> Response(body, options)
</code></pre>
<p>Where <code>body</code> defines the body for the response and <code>options</code> is an object containing custom settings to apply to the response, that is <code>status</code>, <code>statusText</code> and <code>headers</code>.</p>
<p>For example, we could update our <code>index</code> page to return a new response if we were presumably in beta – represented by a simple variable.</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> isBeta = <span class="hljs-literal">true</span>;

<span class="hljs-keyword">if</span> (isBeta) {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-string">"app not available - check back"</span>, {
    <span class="hljs-attr">status</span>: <span class="hljs-number">200</span>,
    <span class="hljs-attr">statusText</span>: <span class="hljs-string">"OK!"</span>,
  });
} 
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Astro<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>We're live!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>Instead of returning the <code>HTML</code> page, we should now have a simple text response sent to the client.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-22-at-10.43.19.png" alt="Returning a simple text response to the client." width="1016" height="688" loading="lazy">
<em>Returning a simple text response to the client.</em></p>
<p>There’s also a <code>response</code> object on the <code>Astro</code> global. Blimey!</p>
<p>But it’s important to note that this is not the same as the <code>Response</code> object constructor. So, rewriting our example to use <code>Astro.response</code> will fail.</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> isBeta = <span class="hljs-literal">true</span>;

<span class="hljs-keyword">if</span> (isBeta) {
  <span class="hljs-comment">// ❌ This is wrong and will fail</span>
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Astro.response(<span class="hljs-string">"app not available - check back"</span>, {
    <span class="hljs-attr">status</span>: <span class="hljs-number">200</span>,
    <span class="hljs-attr">statusText</span>: <span class="hljs-string">"Excellent!"</span>,
  });
}
---
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-22-at-11.28.52.png" alt="Error: Astro.response is not a constructor." width="1239" height="650" loading="lazy">
<em>Error: Astro.response is not a constructor.</em></p>
<p>This is because <code>Astro.response</code> represents the response object initialiser. It’s used to set the <code>options</code> on the server response, i.e., <code>status</code>, <code>statusText</code> and <code>headers</code>.</p>
<p>For example, to set a custom header on the server response, we could do the following:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro </span>
---
Astro.response.headers.set(<span class="hljs-string">"beta_id"</span>, <span class="hljs-string">"some_header_value"</span>);
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Astro<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>We're live!<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>The server will return the <code>HTML</code> page and our custom <code>beta_id</code> header.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-22-at-11.31.50.png" alt="Setting a custom header on the server response." width="1357" height="1056" loading="lazy">
<em>Setting a custom header on the server response.</em></p>
<h3 id="heading-redirect-response">Redirect response</h3>
<p>It is pretty common to receive a client request and perform a redirect on the server.</p>
<p>There are two ways to achieve this in Astro.</p>
<p>The first is to leverage the standard <code>Response</code> object via <code>Response.redirect</code>.</p>
<p>Consider a case where we want to redirect a user to another page if they are not logged in, as shown below:</p>
<pre><code class="lang-js">{<span class="hljs-comment">/** 📂 src/index.astro **/</span>}
---
<span class="hljs-keyword">const</span> getIsLoggedOut = <span class="hljs-function">() =&gt;</span> <span class="hljs-literal">true</span>;
<span class="hljs-keyword">const</span> isLoggedOut = getIsLoggedOut();

<span class="hljs-keyword">if</span> (isLoggedOut) {
  <span class="hljs-keyword">return</span> Response.redirect(<span class="hljs-string">`<span class="hljs-subst">${Astro.request.url}</span>about`</span>, <span class="hljs-number">307</span>);
}
---
</code></pre>
<p>In this example, we call <code>Response.redirect</code> while passing it a redirect URL and a status code, that is:</p>
<pre><code class="lang-js">Response.redirect(URL, status)
</code></pre>
<p>It’s important to note that the <code>URL</code> in this case is an absolute path. So constructing from <code>Astro.request.url</code> that points to the absolute base path, for example <code>http://localhost:3001/</code>.</p>
<p>When logged out, the user will be redirected to the <code>about</code> page and the optional status code <code>307</code> indicates a temporary redirect.</p>
<p>As we’ve seen above, constructing the absolute URL could get unnecessarily complex. Luckily, there’s an alternative way to perform a redirect.</p>
<p>We may also leverage the <code>Astro.redirect</code> method to redirect to another page. For example, we could rewrite our solution to use <code>Astro.redirect</code> as shown below:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> getIsLoggedOut = <span class="hljs-function">() =&gt;</span> <span class="hljs-literal">true</span>;
<span class="hljs-keyword">const</span> isLoggedOut = getIsLoggedOut();

<span class="hljs-keyword">if</span> (isLoggedOut) {
  <span class="hljs-keyword">return</span> Astro.redirect(<span class="hljs-string">"/about"</span>, <span class="hljs-number">307</span>);
}
---
</code></pre>
<p>We have a much simpler API here. We can redirect by just passing the relative path to redirect to. The status code is also optional here.</p>
<p>It’s important to note that redirects should be done in page components, that is not inside other components like layouts or base components.</p>
<h3 id="heading-utilities-for-manipulating-cookies">Utilities for manipulating cookies</h3>
<p>In SSR mode, we may need to read or manipulate cookies. Well, Astro’s got us covered with <code>Astro.cookies</code>. This contains utilities for reading and using cookies in SSR mode.</p>
<p>Consider the examples of retrieving a cookie:</p>
<pre><code class="lang-js"><span class="hljs-comment">//Get an AstroCookie object </span>
<span class="hljs-keyword">const</span> cookieObject = Astro.cookies.get(<span class="hljs-string">"coooookiee"</span>)

<span class="hljs-comment">// Get the string value of the cookie </span>
<span class="hljs-keyword">const</span> cookieValue = cookieObject.value 

<span class="hljs-comment">// Parse the cookie value via JSON.parse. Returns an object if the cookie is a valid JSON. It throws an error otherwise. </span>

<span class="hljs-keyword">const</span> cookieJSON = cookieObject.json()

<span class="hljs-comment">// Parse the cookie value as a Number </span>
<span class="hljs-keyword">const</span> cookieNumber = cookieObject.number() 

<span class="hljs-comment">// Parse the cookie as a boolean </span>
<span class="hljs-keyword">const</span> cookieBoolean = cookieObject.boolean()
</code></pre>
<p>That’s a lot of flexibility!</p>
<p>We may also check if a cookie exists with the <code>has</code> method, as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// check if the "cooooookies" cookie exists. returns a boolean</span>
<span class="hljs-keyword">const</span> hasCookie = Astro.cookies.has(<span class="hljs-string">'cooooookies'</span>)
</code></pre>
<p>It is also possible to set a cookie as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Set a cookie </span>
Astro.cookies.set(<span class="hljs-string">"cooookiees"</span>, <span class="hljs-string">"the-cookie-value"</span>)
</code></pre>
<p>The signature for <code>Astro.cookies.set</code> is shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Astro.set(key, value, options)</span>
<span class="hljs-attr">key</span>: string, 
<span class="hljs-attr">value</span>: string | number | boolean | object,
options?: CookieOptions) =&gt; <span class="hljs-keyword">void</span>
</code></pre>
<p>Note how different cookie value types may be set and additional cookie <a target="_blank" href="https://www.npmjs.com/package/cookie#options-1">options</a> passed if needed, for example <code>domain</code>, <code>encode</code>, <code>expires</code>, <code>maxAge</code> or <code>httpOnly</code>.</p>
<h3 id="heading-the-request-ip-address">The request IP address</h3>
<p>Understanding <a target="_blank" href="https://www.freecodecamp.org/news/ipv4-vs-ipv6-what-is-the-difference-between-ip-addressing-schemes/">IP addresses</a> is beyond the scope of this book. But, we may gain access to the request’s IP address on the server via the <code>Astro.clientAddress</code> property.</p>
<p>Below’s a simple example:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> ip = Astro.clientAddress;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>Your IP address is: {ip}<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
</code></pre>
<h2 id="heading-environment-variables">Environment Variables</h2>
<p>If you’re completely new to environment variables, you might the thinking, <em>"Oi, what are Environment variables, and why should I care?"</em></p>
<p>Generally speaking, environment variables help us store important information like API keys or sensitive data without ever having to reveal them to clients accessing your application.</p>
<p>Like any secret, environment variables can be arguably slightly tricky to handle. You need to know exactly where to find them, how to use them, and most importantly, how to keep them safe from prying eyes.</p>
<h3 id="heading-how-to-get-environment-variables">How to get environment variables</h3>
<p>In Astro, environment variables are accessed on the <code>import.meta.env</code> object.</p>
<p>So, for example, if we had a <code>CAT_API_TOKEN</code> value, we would access it as follows:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span>.meta.env.CAT_API_TOKEN
---
</code></pre>
<p>If you’re conversant with environment variables in node environments, you’ll notice that this differs from the classic <code>process.env</code> object. Astro leverages Vite, which uses the <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/import.meta">import.meta</a> JavaScript feature.</p>
<h3 id="heading-default-environment-variables">Default environment variables</h3>
<p>We all have secrets.</p>
<p>Well, I’m not quite sure of that. Let me rephrase: most people have secrets.</p>
<p>Similarly, every Astro project has some default secrets, aka environment variables, out of the box. Consider the defaults below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// Get the mode the Astro site is running in: "development" | "production" </span>
<span class="hljs-keyword">import</span>.meta.env.MODE 

<span class="hljs-comment">// Is the site running in production? returns true or false </span>
<span class="hljs-keyword">import</span>.meta.env.PROD 

<span class="hljs-comment">// Is the site running in development? returns true or false </span>
<span class="hljs-keyword">import</span>.meta.env.DEV 

<span class="hljs-comment">// The base URL of the Astro site </span>
<span class="hljs-keyword">import</span>.meta.env.BASE_URL

<span class="hljs-comment">// Get the final deployed URL of the Astro site</span>
<span class="hljs-keyword">import</span>.meta.env.SITE

<span class="hljs-comment">// Get prefix for Astro-generated asset links </span>
<span class="hljs-keyword">import</span>.meta.env.ASSETS_PREFIX
</code></pre>
<p>For <code>import.meta.env.BASE_URL</code>, it’s important to note that this will default to <code>/</code> except explicitly stated in the project configuration. For example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'astro/config'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
   <span class="hljs-attr">base</span>: <span class="hljs-string">'/docs'</span>
})
</code></pre>
<p>Astro will now use <code>/docs</code> as the root for our pages and assets in the development and production build.</p>
<p>Similarly, <code>import.meta.env.SITE</code> relies on the <code>site</code> property set in the astro config, for example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">'astro/config'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
   <span class="hljs-attr">site</span>: <span class="hljs-string">'https://www.ohansemmanuel.com'</span>
})
</code></pre>
<p>Astro will use this full URL to generate the site’s sitemap and canonical URLs where relevant.</p>
<p><code>import.meta.env.ASSETS_PREFIX</code> also relies on the <code>build.assetsPrefix</code> option set in the project’s config, for example:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span>  defineConfig  <span class="hljs-keyword">from</span> <span class="hljs-string">'astro/config'</span>

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">build</span>: {
    <span class="hljs-attr">assetsPrefix</span>: <span class="hljs-string">'https://cdn.example.com'</span>
  }
})
</code></pre>
<p>This can be used if assets are served from a different domain than the current site. For example with the <code>https://cdn.example.com</code> prefix, assets will be fetched from <code>https://cdn.example.com/_astro/...</code>. This implies the files in the default astro build directory <code>./dist/astro</code> must be uploaded to the CDN directory to serve the assets.</p>
<p>Phew! Out with the secrets.</p>
<h3 id="heading-how-to-create-environment-variables">How to create environment variables</h3>
<p>It doesn’t do a lot of good if we can’t create our own secrets. Heck, it helps with the mystic.</p>
<p>The most common way to create environment variables is to use <code>.env</code> files.</p>
<p>For example, let’s go ahead and create a <code>.env</code> file in the root directory of our project directory with the following content:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/.env </span>
CAT_API_TOKEN=<span class="hljs-string">"this-is-the-cat-production-token"</span>
</code></pre>
<p>We may then access the secret server-side via <code>import.meta.env.CAT_API_TOKEN</code>.</p>
<p>I must mention that exposing certain environment variables to the client (browser) is possible. To do this, prefix the environment variable with a <code>PUBLIC_</code>, for example:</p>
<pre><code class="lang-js">PUBLIC_INSENSITIVE_TOKEN=<span class="hljs-string">"this-is-public"</span>
</code></pre>
<p><code>PUBLIC_INSENSITIVE_TOKEN</code> will now be accessible both on the server and client. That’s an open secret. Anyone, and I mean anyone, can see your dirty laundry here. Only use this for insensitive environment variables.</p>
<p>Remember that environment variables are only available in server-side code by default. Prefix environment variables with <code>PUBLIC_</code> to expose them to the client.</p>
<p>It is also possible to run your project and provide environment variables from the CLI, as shown below:</p>
<pre><code class="lang-bash">CAT_API_TOKEN=<span class="hljs-string">"this-is-the-cat-production-token npm run dev"</span>
</code></pre>
<p>In this case, <code>CAT_API_TOKEN</code> will be available both server-side and client-side. Use with caution. We only tell people we trust secrets and never blindly trust a client, like a user browser.</p>
<h3 id="heading-typescript-intellisense">TypeScript IntelliSense</h3>
<p>We don't get TypeScript IntelliSense support if we attempt to access <code>CAT_API_TOKEN</code> in <code>pages/index.astro</code> after creating the <code>.env</code> file.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-23-at-09.44.07.png" alt="No Typescript IntelliSense for our custom environment variable." width="591" height="206" loading="lazy">
<em>No Typescript IntelliSense for our custom environment variable.</em></p>
<p>We’re pro developers, so come on – let’s fix this.</p>
<p>We’ll find a <code>src/env.d.ts</code> file with projects started with an Astro template. Otherwise, go ahead and create one.</p>
<p>Here’s the initial content of the file if it already exists:</p>
<pre><code class="lang-ts"><span class="hljs-comment">/// &lt;reference types="astro/client" /&gt;</span>
</code></pre>
<p>Let’s extend the default <code>ImportMeta</code> interface that provides type definitions for <code>import.meta.env</code> by adding the following:</p>
<pre><code class="lang-ts"><span class="hljs-keyword">interface</span> ImportMetaEnv {
  <span class="hljs-keyword">readonly</span> CAT_API_TOKEN: <span class="hljs-built_in">string</span>;
  <span class="hljs-comment">// add other custom env variables...</span>
}
</code></pre>
<p>And voilà! TypeScript knows our secrets – for the better.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-23-at-09.50.10.png" alt="Typescript IntelliSense activated." width="663" height="255" loading="lazy">
<em>Typescript IntelliSense activated.</em></p>
<h2 id="heading-dynamic-routes">Dynamic Routes</h2>
<p>Static routes are arguably easy to reason about. For example, <code>.astro</code>, <code>.md</code> and <code>.mdx</code> files in <code>src/pages</code> will automatically become pages on our website.</p>
<p>But sometimes we require dynamic routes to prevent repetition. This typically happens when we have different routes with minimal UI changes between them.</p>
<p>For example, if we were selling products on our website, we would have a different route for each product.</p>
<pre><code class="lang-ts"><span class="hljs-comment">// example routes for different products </span>
www.example.com/product/understanding-astro
www.example.com/product/astro-a-to-z
www.example.com/product/astro-<span class="hljs-keyword">for</span>-beginners
www.example.com/product/fullstack-astro
</code></pre>
<pre><code class="lang-ts"><span class="hljs-comment">// ❌ Providing multiple pages for each product</span>
/pages/understanding-astro.astro
/pages/astro-a-to-z
/pages/astro-<span class="hljs-keyword">for</span>-beginners
/pages/fullstack-astro
</code></pre>
<p>The URL structure of the product pages could be represented by <code>www.example.com/product/${name}</code> where <code>name</code> means the product’s name.</p>
<p>Instead of creating different pages to represent each product, we may dynamically handle the product routing in one of two ways.</p>
<h3 id="heading-1-named-parameters-1">1. Named parameters</h3>
<p>We could represent the variables in the route path with a named parameter surrounded by square brackets. For example, creating a file in the <code>pages</code> directory as follows:</p>
<pre><code class="lang-js">/pages/products/[product].astro
</code></pre>
<p>We may then grab the <code>product</code> path value on the page as follows:</p>
<pre><code class="lang-js">{<span class="hljs-comment">/** 📂 src/pages/[product].astro **/</span>}
&lt;h1&gt;{Astro.params.product}&lt;/h1&gt;
</code></pre>
<p>Alternatively:</p>
<pre><code class="lang-js">---
 <span class="hljs-keyword">const</span> {product} = Astro.params 
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{product}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p>Now if we visit the <code>/products/understanding-astro</code> page, we should have the title of the product displayed.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-24-at-10.25.23.png" alt="Grabbing dynamic route path values." width="828" height="544" loading="lazy">
<em>Grabbing dynamic route path values.</em></p>
<p>In most cases, our variable path parameter will include a unique identifier, for example <code>/pages/products/[id].astro</code>.</p>
<p>The same routing works.</p>
<p>It is also possible to leverage multiple named parameters in the route path, as shown below:</p>
<pre><code class="lang-js">{<span class="hljs-comment">/** /products/[product]_[id].astro **/</span>}
&lt;h1&gt;Product name: {Astro.params.product}&lt;/h1&gt;
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Product id: {Astro.params.id}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p>This will be matched with a URL similar to <code>/products/understanding-astro_09u34359534530903453450</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-24-at-10.31.22.png" alt="Matching multiple route named parameters." width="1158" height="824" loading="lazy">
<em>Matching multiple route named parameters.</em></p>
<h3 id="heading-2-rest-parameters-1">2. Rest parameters</h3>
<p>Rest parameters provide ultimate flexibility in our URL routing. For example, we may use <code>[...path]</code> to match file paths of any depth. Where <code>path</code> could be represented by any string, like <code>[...file]</code> or <code>[...somestring]</code>.</p>
<p>Consider the following product pages:</p>
<pre><code class="lang-js">/products/product-id
/products/category/product-id/
<span class="hljs-regexp">/products/</span>types/category/product-id
</code></pre>
<p>The routes above will all be matched by the page <code>pages/product/[...path].astro</code>, and we can access the full dynamic string path within our code.</p>
<p>For example, create a file in <code>/pages/product/[...path].astro</code> with the following content:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> { path } = Astro.params;
<span class="hljs-built_in">console</span>.log({ path });
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Hello there<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p>For the paths above, the <code>path</code> variable corresponds to <code>product-id</code>, <code>category/product-id</code> and <code>types/category/product-id</code>.</p>
<p>With much power comes much responsibility.</p>
<p>With the increased flexibility rest path parameters provide comes the responsibility of handling the paths in our code. For example, consider how we may handle the multiple product paths below:</p>
<pre><code class="lang-js">---
<span class="hljs-comment">// Get the dynamic route path </span>
<span class="hljs-keyword">const</span> { path } = Astro.params;

<span class="hljs-comment">// Hold a list of all expected paths and corresponding data, e.g., title.</span>
<span class="hljs-keyword">const</span> page = [
  {
    <span class="hljs-attr">path</span>: <span class="hljs-literal">undefined</span>,
    <span class="hljs-attr">title</span>: <span class="hljs-string">"View all products"</span>
  },
  {
    <span class="hljs-attr">path</span>: <span class="hljs-string">"product-id"</span>,
    <span class="hljs-attr">title</span>: <span class="hljs-string">"Some Product"</span>,
  },
  {
    <span class="hljs-attr">path</span>: <span class="hljs-string">"category/product-id"</span>,
    <span class="hljs-attr">title</span>: <span class="hljs-string">"Some Product Category Item"</span>,
  },
  {
    <span class="hljs-attr">path</span>: <span class="hljs-string">"types/category/product-id"</span>,
    <span class="hljs-attr">title</span>: <span class="hljs-string">"Some Product Type Category Item"</span>,
  },
];

<span class="hljs-comment">//Is this a valid path? i.e., exists in our list? </span>
<span class="hljs-keyword">const</span> relevantPageDetails = page.find(<span class="hljs-function">(<span class="hljs-params">v</span>) =&gt;</span> v.path === path);

<span class="hljs-keyword">if</span> (!relevantPageDetails) {
  <span class="hljs-comment">// redirect if the dynamic page isn't valid.</span>
  <span class="hljs-keyword">return</span> Astro.redirect(<span class="hljs-string">"/404"</span>);
}
---

<span class="hljs-comment">// render the title of the page </span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{relevantPageDetails.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-24-at-12.42.28@2x.png" alt="Rendering rest parameter routes." width="2000" height="1305" loading="lazy">
<em>Rendering rest parameter routes.</em></p>
<p>It’s important to note that if the <code>path</code> is undefined, the root path will be matched, that is it corresponds to <code>pages/product</code>.</p>
<p>While this demonstrates using rest paths in server-side rendered pages, it is a contrived example where we’ve assumed the literal string “product-id”.</p>
<p>In the real world, the literal string will be represented by different product id strings rather than <code>product-id</code> – and we might not know what these are ahead of time.</p>
<p>As we’ve done in the previous solution, keeping a massive list of all product IDs in our application becomes unmaintainable.</p>
<p>For this use case, one way to achieve this would be to update our solution to have sufficiently complex matching logic, for example via regular expressions, because we don’t know the product IDs beforehand.</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">const</span> { path = <span class="hljs-string">"index"</span> } = Astro.params;

<span class="hljs-keyword">const</span> page = [
  {
    <span class="hljs-attr">match</span>: <span class="hljs-regexp">/some-regex/</span>,
    title: <span class="hljs-string">"View all products"</span>,
  },
  {
    <span class="hljs-attr">match</span>: <span class="hljs-regexp">/some-regex/</span>,
    title: <span class="hljs-string">"Some Product"</span>,
  },
  {
    <span class="hljs-attr">match</span>: <span class="hljs-regexp">/some-regex/</span>,
    title: <span class="hljs-string">"Some Product Category Item"</span>,
  },
  {
    <span class="hljs-attr">match</span>: <span class="hljs-regexp">/some-regex/</span>,
    title: <span class="hljs-string">"Some Product Type Category Item"</span>,
  },
];

<span class="hljs-keyword">const</span> relevantPageDetails = page.find(<span class="hljs-function">(<span class="hljs-params">v</span>) =&gt;</span> path.match(v.match));

<span class="hljs-keyword">if</span> (!relevantPageDetails) {
  <span class="hljs-keyword">return</span> Astro.redirect(<span class="hljs-string">"/404"</span>);
}
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>{relevantPageDetails.title}<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p>As a matter of personal preference, I’ve sworn a blood oath to avoid path rest parameters for multiple SSR page paths when I can’t deterministically determine the path variables beforehand.</p>
<p>Simple is sometimes better.</p>
<p>In this case, I suggest separating the pages, that is creating multiple directories and letting the default Astro automatic routing kick in.</p>
<p>For example, match the path <code>category/product-id</code> by creating a page in <code>category/[id]</code> and <code>types/category/[id]</code> to match the route <code>types/category/product-id</code>.</p>
<p>They can also be composed with a common layout or shared components if they have identical user interfaces.</p>
<h3 id="heading-priority-order-1">Priority order</h3>
<p>As we’ve discussed above, URL paths can be matched in different ways, so what happens when different file paths match the same URL path in our project?</p>
<p>Well, Astro needs to make a decision, so lets review the priority list below:</p>
<ol>
<li>Static routes, that is those without path parameters, have the highest priority, for example <code>/pages/products/this-is-a-product</code>.</li>
<li>Dynamic routes with named parameters have the next priority, for example <code>/pages/products/[id]</code>.</li>
<li>Dynamic routes with rest parameters have the lowest priority, for example <code>/pages/products/[...path]</code>.</li>
<li>Following the above, any ties will be resolved alphabetically.</li>
</ol>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/route_priority.png" alt="Route priority order from first to last." width="2138" height="735" loading="lazy">
<em>Route priority order from first to last.</em></p>
<h2 id="heading-server-endpoints">Server Endpoints</h2>
<p>Server endpoints are like the secret weapons in our arsenal when running server-side functions.</p>
<p>They can be used as REST API endpoints to run functions such as database access, authentications, and verifications without exposing sensitive data to the client, that is we can securely execute code on the server at runtime in these functions.</p>
<p>Consider the current state of our project with a <code>page/products</code> directory. What if we wanted to create an API route to handle some client requests? How would we do this?</p>
<h3 id="heading-how-to-create-server-endpoints">How to create server endpoints</h3>
<p>To create an API route in the <code>server</code> output mode, create a <code>.ts</code> or <code>.js</code> file within the <code>pages</code> directory. Optionally, you may see endpoints created with the type of data the endpoint returns in the file name, for example <code>.json.ts</code>.</p>
<p>I prefer to keep server endpoints simple and omit additional file names. Let’s go ahead and create an <code>api.ts</code> file and handle incoming <code>GET</code> requests as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 pages/products/api</span>
<span class="hljs-keyword">import</span> type { APIRoute } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> get: APIRoute = <span class="hljs-function">(<span class="hljs-params">ctx</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
      <span class="hljs-attr">message</span>: <span class="hljs-string">"Hello world"</span>,
    }),
  };
};
</code></pre>
<ul>
<li>Note the <code>APIRoute</code> type used on the <code>get</code> function. This represents the API route function type definition.</li>
<li>Every API route function receives a context object, for example represented by <code>ctx</code>. The <a target="_blank" href="https://docs.astro.build/en/reference/api-reference/#endpoint-context">context object</a> contains relevant properties we’ll take a look at shortly.</li>
<li>As shown above, an API route function can return a response with a <code>body</code>. The complete response form is shown below:<br>      <code>{</code><br>         <code>body: string</code><br>         <code>encoding?: 'ascii' | 'utf8' | 'utf-8' | 'utf16le' |</code><br>               <code>'ucs2' | 'ucs-2' | 'base64' | 'base64url' |</code><br>                <code>'latin1' | 'binary' | 'hex'</code><br>      <code>}</code><br>We may also return a standard response via the Response object as shown below:<br>      <code>import type { APIRoute } from "astro";</code><br>      <code>` </code>export const get: APIRoute = (ctx) =&gt; {<code>`return new Response(JSON.stringify({</code><br>          <code>message: "Hello world"</code><br>          <code>}), {</code><br>           <code>status: 200,</code><br>        <code>});</code><br>      <code>};</code></li>
</ul>
<h3 id="heading-request-details">Request details</h3>
<p>Accessing details of the request object is a breeze with API routes. For example, we may access the request object on the context object to check its headers, as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> type { APIRoute } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> get: APIRoute = <span class="hljs-function">(<span class="hljs-params">ctx</span>) =&gt;</span> {
  <span class="hljs-comment">// check for an Authorization header on the request</span>
  <span class="hljs-keyword">const</span> auth = ctx.request.headers.get(<span class="hljs-string">"Authorization"</span>);

  <span class="hljs-comment">// The user is unauthorised to get this resource</span>
  <span class="hljs-keyword">if</span> (!auth) {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Unauthorized"</span> }), {
      <span class="hljs-attr">status</span>: <span class="hljs-number">401</span>,
    });
  }

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Hello world"</span> }), {
    <span class="hljs-attr">status</span>: <span class="hljs-number">200</span>,
  });
};
</code></pre>
<p>We could also destructure properties of the context object, for example the request object, as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> get: APIRoute = <span class="hljs-function">(<span class="hljs-params">{ request }</span>) =&gt;</span> {
  <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>While getting the <code>request</code> object is great, consider the complete list of properties available on the endpoint context object:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> get: APIRoute = <span class="hljs-function">(<span class="hljs-params">{
  url,
  site,
  params,
  request,
  cookies,
  generator,
  redirect,
  clientAddress,
}</span>) =&gt;</span> {
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">message</span>: <span class="hljs-string">"Hello world"</span> }), {
    <span class="hljs-attr">status</span>: <span class="hljs-number">200</span>,
  });
};
</code></pre>
<p>Some of these should be familiar from discussing the request and response objects on the <code>Astro</code> global; however, here’s a quick breakdown:</p>
<table>
    <thead>
        <tr>
            <th>
                Property
            </th>
            <th>
                 What?
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <br>url
            </td>
            <td>
                <br>A standard <a href="https://developer.mozilla.org/en-US/docs/Web/API/URL">URL</a> interface. <br>
            </td>
        </tr>
        <tr>
            <td>
                <br>site
            </td>
            <td>
                <br>The site property from the astro configuration file.<br>
            </td>
        </tr>
        <tr>
            <td>
                <br>params
            </td>
            <td>
                <p><br>An object containing values of the dynamic </p>

                <p>path segments matched by the request.</p>
            </td>
        </tr>
        <tr>
            <td>
                <br>request
            </td>
            <td>
                <br>A standard <a href="https://developer.mozilla.org/en-US/docs/Web/API/Request">Request</a> interface of the Fetch API.<br>
            </td>
        </tr>
        <tr>
            <td>
                <br>cookies
            </td>
            <td>
                <br>Similar to Astro.cookies. It contains utilities <br>for reading and manipulating cookies.
            </td>
        </tr>
        <tr>
            <td>
                <br>generator
            </td>
            <td>
                <br>Indicates the version of Astro our project is running.<br>
            </td>
        </tr>
        <tr>
            <td>
                <br>redirect
            </td>
            <td>
                <br>Similar to Astro.redirect. <br>
            </td>
        </tr>
        <tr>
            <td>
                <br>clientAddress
            </td>
            <td>
                <br>Specifies the IP address of the request. <br>Similar to Astro.clientAddress
            </td>
        </tr>
    </tbody>
</table>

<p>The alien properties here are <code>generator</code>, <code>url</code> and <code>params</code>.</p>
<p><code>generator</code> is easy to reason about, while <code>url</code> represents a <a target="_blank" href="https://developer.mozilla.org/en-US/docs/Web/API/URL">URL</a> object constructed from <code>request.url</code>, that is identical to <code>new URL(request.url)</code>.</p>
<p>It’s worth mentioning that a similar object may be accessed on the <code>Astro</code> global via <code>Astro.url</code>. This could come in handy in static pages.</p>
<p>What about <code>params</code>? Well, that requires a separate section when we discuss dynamic routes.</p>
<h3 id="heading-dynamic-api-routes">Dynamic API routes</h3>
<p>The dynamic route fabric on pages works the same magic on API endpoints.</p>
<p>For example, our API endpoint is in the <code>pages/products/api</code> file. What if we wanted client requests to be made in the format: <code>GET /api/products/${id}</code>?</p>
<p>Did you notice the variable <code>id</code>?</p>
<p>In this case, we may leverage dynamic routes as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 pages/api/products/[id]</span>

<span class="hljs-keyword">import</span> type { APIRoute } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> get: APIRoute = <span class="hljs-keyword">async</span> (ctx) =&gt; {
  <span class="hljs-comment">// Get the product ID </span>
  <span class="hljs-keyword">const</span> productId = ctx.params.id;

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://fakestoreapi.com/products/1"</span>);
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ 
     ...data, 
     <span class="hljs-comment">// Add the ID in the response body</span>
     <span class="hljs-attr">id</span>: productId 
    }), {
      <span class="hljs-attr">status</span>: <span class="hljs-number">200</span>,
    });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ 
        <span class="hljs-attr">message</span>: <span class="hljs-string">"An error occurred."</span> 
      }), {
      <span class="hljs-attr">status</span>: <span class="hljs-number">500</span>,
    });
  }
};
</code></pre>
<p>I might have sprung a surprise on you in the code block above. But the main difference here is we’re reaching out to some external API (think fetching data from a database) and sending the response back to the client.</p>
<p>Another critical point is to notice how the specific id is retrieved from <code>ctx.params.id</code>, where <code>ctx</code> represents the context object.</p>
<p>If we make a GET request to <code>api/products/astro-book-001</code>, we should have some data returned to the client.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-25-at-08.57.00@2x.png" alt="Testing the product API on hopscotch.io" width="2246" height="1774" loading="lazy">
<em>Testing the product API on hopscotch.io</em></p>
<p>Note how whatever “id” is passed in the request path is rightly retrieved, for example <code>astro-book-001</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-25-at-08.49.31@2x.png" alt="The product ID returned in the JSON response." width="1442" height="420" loading="lazy">
<em>The product ID returned in the JSON response.</em></p>
<p>To re-iterate, we can get the path segments in the dynamic route pattern via <code>context.params</code> and voilà! We have our use case resolved.</p>
<p>Passing query parameters to <code>GET</code> requests is not unheard of in the real world. Heck, it’s quite an everyday use case in fact.</p>
<p>Assuming the following client request <code>GET api/products/astro-book-001?version=2&amp;publishedDate=2023-06-12</code>, how would we handle this?</p>
<p>It’s important to note that <code>version</code> and <code>publishedDate</code> will not be present in <code>context.params</code>. But we can grab these from the <code>URL</code> object as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 pages/api/products/[id]</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> get: APIRoute = <span class="hljs-keyword">async</span> (ctx) =&gt; {
  <span class="hljs-keyword">const</span> productId = ctx.params.id;

  <span class="hljs-comment">// retrieve relevant search parameters, aka URL query parameters</span>
  <span class="hljs-keyword">const</span> searchParams = ctx.url.searchParams;
  <span class="hljs-keyword">const</span> version = searchParams.get(<span class="hljs-string">"version"</span>);
  <span class="hljs-keyword">const</span> publishedDate = searchParams.get(<span class="hljs-string">"publishedDate"</span>);

  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://fakestoreapi.com/products/1"</span>);
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();

    <span class="hljs-comment">// Return a new response with the retrieved </span>
    <span class="hljs-comment">// "version" and "publishedDate"</span>
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(
      <span class="hljs-built_in">JSON</span>.stringify({ 
        ...data, 
        version, 
        publishedDate, 
        <span class="hljs-attr">id</span>: productId 
       }),
      {
        <span class="hljs-attr">status</span>: <span class="hljs-number">200</span>,
      }
    );
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ 
      <span class="hljs-attr">message</span>: <span class="hljs-string">"An error occurred"</span> }), {
      <span class="hljs-attr">status</span>: <span class="hljs-number">500</span>,
    });
  }
};
</code></pre>
<p>The crux of the solution is the following:</p>
<pre><code class="lang-js"> <span class="hljs-comment">// retrieve relevant search parameters, aka URL query parameters</span>
  <span class="hljs-keyword">const</span> searchParams = ctx.url.searchParams;
  <span class="hljs-keyword">const</span> version = searchParams.get(<span class="hljs-string">"version"</span>);
  <span class="hljs-keyword">const</span> publishedDate = searchParams.get(<span class="hljs-string">"publishedDate"</span>);
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-25-at-09.13.04@2x.png" alt="Retrieving query parameters in a server endpoint." width="2246" height="1774" loading="lazy">
<em>Retrieving query parameters in a server endpoint.</em></p>
<h3 id="heading-dedicated-api-directory">Dedicated API directory</h3>
<p>At the time of writing, API routes must live in the <code>pages</code> directory with appropriate file endings, for example <code>.ts</code> or <code>.js</code>.</p>
<p>For example, you can have <code>pages/anyFileName.js</code> act as a server endpoint.</p>
<p>But I find it easier (and better) to have my server API routes in a dedicated <code>pages/api</code> directory instead of mixing these in other page routes.</p>
<p>One advantage to this is potentially making it easier to redirect a subdomain to a single path for all API routes, for example redirect <code>api.my-website.com/...</code> to <code>my-website.com/api/...</code>.</p>
<p>On the flip side, an arguable downside is we break the collocation of other routes, for example standard pages such as <code>pages/products/...</code> will have their associated API route in <code>api/products/...</code>. This is a downside and a trade-off I happily make in production applications.</p>
<h3 id="heading-how-to-support-other-http-methods">How to support other HTTP methods</h3>
<p>All our examples so far have used the get method within our API routes. But Astro does support all the other HTTP methods, such as post or delete.</p>
<p>Consider the following example that extends our <code>api/products/${id}</code> endpoint to include more methods:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> type { APIRoute } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;

<span class="hljs-comment">// Handle client GET requests </span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> get: APIRoute = <span class="hljs-keyword">async</span> (ctx) =&gt; {
  <span class="hljs-keyword">const</span> productId = ctx.params.id;
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// fetch remote resource </span>
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://fakestoreapi.com/products/1"</span>);
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();

    <span class="hljs-comment">// return data, and the id param</span>
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ 
      ...data, 
      <span class="hljs-attr">id</span>: productId 
    }), {
      <span class="hljs-attr">status</span>: <span class="hljs-number">200</span>,
    });
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ 
      <span class="hljs-attr">message</span>: <span class="hljs-string">"An error occurred"</span> }), {
      <span class="hljs-attr">status</span>: <span class="hljs-number">500</span>,
    });
  }
};

<span class="hljs-comment">/**
 * Handle "DELETE" requests
 * "delete" is a reserved word in Javascript. Hence, the function name "del"
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> del: APIRoute = <span class="hljs-keyword">async</span> (ctx) =&gt; {
  <span class="hljs-keyword">const</span> productId = ctx.params.id;
  <span class="hljs-keyword">try</span> {
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"https://fakestoreapi.com/products/1"</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">"DELETE"</span>,
    });
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> response.json();

    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(
      <span class="hljs-built_in">JSON</span>.stringify({ 
        <span class="hljs-attr">id</span>: productId, 
        <span class="hljs-attr">message</span>: <span class="hljs-string">"deleted"</span>, 
        <span class="hljs-attr">title</span>: data.title }),
      {
        <span class="hljs-attr">status</span>: <span class="hljs-number">202</span>,
      }
    );
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ 
      <span class="hljs-attr">message</span>: <span class="hljs-string">"An error occurred"</span> }), {
      <span class="hljs-attr">status</span>: <span class="hljs-number">500</span>,
    });
  }
};

<span class="hljs-comment">/**
 * Handle "POST" requests
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> post: APIRoute = <span class="hljs-keyword">async</span> (ctx) =&gt; {
  <span class="hljs-comment">// Get the POST body data</span>
  <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> ctx.request.json();

  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-built_in">JSON</span>.stringify({ 
    <span class="hljs-attr">message</span>: <span class="hljs-string">"Created"</span>, data 
  }));
};
</code></pre>
<p>Go ahead and give these a try!</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-25-at-08.53.33@2x.png" alt="Making a POST request to our server endpoint." width="2246" height="1774" loading="lazy">
<em>Making a POST request to our server endpoint.</em></p>
<p>As a fallback to handle other HTTP methods, we can provide an <code>all</code> function to match methods that don’t have a corresponding exported function. Consider the example below:</p>
<pre><code class="lang-js">... 
export <span class="hljs-keyword">const</span> all: APIRoute = <span class="hljs-keyword">async</span> (ctx) =&gt; {
  <span class="hljs-comment">// Get the request method</span>
  <span class="hljs-keyword">const</span> method = ctx.request.method;

  <span class="hljs-comment">// Return a response</span>
  <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(
    <span class="hljs-built_in">JSON</span>.stringify({
      method,
      <span class="hljs-attr">message</span>: <span class="hljs-string">"Unsupported HTTP method"</span>,
    }),
    {
      <span class="hljs-attr">status</span>: <span class="hljs-number">501</span>, <span class="hljs-comment">// unsupported</span>
    }
  );
};
</code></pre>
<p>This will match unhandled methods in our implementation, such as <code>PATCH</code> requests.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-25-at-08.56.25@2x.png" alt="Handling unsupported methods in a server endpoint." width="2246" height="1774" loading="lazy">
<em>Handling unsupported methods in a server endpoint.</em></p>
<h2 id="heading-streams-oh-streams">Streams, Oh Streams</h2>
<p>I’ve chosen a playful title for this section as it involves a relatively lesser-known feature of Astro: server streaming.</p>
<h3 id="heading-what-is-server-streaming">What is server streaming?</h3>
<p>Generally speaking, SSR refers to generating HTML on the server and sending that to a browser in response to a request.</p>
<p>In theory, we may break this off into distinct steps:</p>
<ul>
<li>Browser requests a page</li>
<li>The server renders the page (and every associated data)</li>
<li>The server returns the <strong>fully formed page</strong> to the browser</li>
<li>The browser renders the page</li>
</ul>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/send_full_page.png" alt="Server sending a fully formed page to the client." width="2000" height="377" loading="lazy">
<em>Server sending a fully formed page to the client.</em></p>
<p>What’s important here is to note that the server generates the page’s full HTML, and only then does it send the HTML to the browser.</p>
<p>Now, consider a different approach.</p>
<p>In most cases, certain parts of the HTML page are static and could be sent from the server immediately, that is without relying on fetching all the relevant data.</p>
<p>What if the server could transmit the <code>HTML</code> to the browser as it creates the page server side?</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/server_send_chunks.png" alt="The server sends partial chunks to the browser." width="2000" height="377" loading="lazy">
<em>The server sends partial chunks to the browser.</em></p>
<p>This is the crux of streaming: stream HTML to a browser as the server generates the HTML.</p>
<h3 id="heading-why-should-we-bother">Why should we bother?</h3>
<p>In theory, browsers can render partial HTML and support receiving and rendering HTML data in chunks. Users can view and interact with a page as it streams rather than waiting for the full page to be sent as one big chunk.</p>
<p>Different applications will need various workarounds. But streaming improves server overhead. The server doesn’t need as much memory to buffer entire pages. It’ll incrementally send page data to the browser releasing memory to handle more requests and consequently save overhead costs. </p>
<p>This is a great argument to convince your boss that streaming is good for the company’s wallets (except if your company plays the silly game of <em>burning as much cash as possible</em>).</p>
<h3 id="heading-streaming-is-easy-yet-difficult">Streaming is easy yet difficult</h3>
<p>I’ve sung the praises of streaming. It is conceptually easy to reason about. But in practice you may experience some difficult use cases.</p>
<p>A great example is considering the <code>&lt;title&gt;</code> of a page that goes in our HTML’s <code>&lt;head&gt;</code>. Typically, the <code>&lt;head&gt;</code> is one of the first elements we stream to the browser. But some elements within the <code>&lt;head&gt;</code> could very well be dynamic, for example we may have a <code>&lt;title&gt;</code> in the form <code>&lt;title&gt;{product name} fetched from the server&lt;title&gt;</code>.</p>
<p>What’s likely to happen is we stream a stale <code>&lt;title&gt;</code> before we eventually get the product name from the database (assuming the database is the external source of data here).</p>
<p>This out-of-order streaming represents some of the most common issues we may face in practice. In this example, we may provide a generic <code>&lt;title&gt;</code> placeholder and continue streaming.</p>
<p>Once the data becomes available server-side, we may stream a tiny <code>&lt;script&gt;</code> that updates the page title to the desired value.</p>
<p>Okay, that’s enough backstory. Next, let’s dig into streaming in Astro.</p>
<h3 id="heading-server-streaming-in-astro">Server streaming in Astro</h3>
<p>Now that you’re convinced (not confused) about the importance of server streaming, let’s explore how streaming in Astro works.</p>
<p>Perhaps the most important thing to know is that Astro supports streaming by default. Yes, you heard that right. Browsers also natively support HTML streaming.</p>
<p>Essentially, within the Astro template, Astro will stream out HTML that occurs before hitting an async boundary.</p>
<p>For example, consider the basic page with a <code>&lt;LoadPets/&gt;</code> component responsible for fetching and rendering some pet data from a database.</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> LoadPets <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/LoadPets.astro'</span>
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
 <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span> 
   <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span> Petsssss! <span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span> 
 <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>This is a pet site<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span> Consider how pets are awesome ... <span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
   <span class="hljs-tag">&lt;<span class="hljs-name">LoadPets</span> /&gt;</span>
 <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>In this contrived example, Astro will steam out the <code>&lt;head&gt;</code>, <code>&lt;h1&gt;</code> and <code>&lt;p&gt;</code> sections to the browser before stopping to fetch the data in <code>&lt;LoadPets /&gt;</code> and then stream its result to the browser when ready.</p>
<p>Let’s explore a visual example.</p>
<p>Update the <code>ssr</code> project to have a new <code>streaming.astro</code> page with the following content:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> Block <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Block.astro"</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Streaming<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Block</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"Block #1"</span> <span class="hljs-attr">delay</span>=<span class="hljs-string">{1000}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Block</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"Block #2"</span> <span class="hljs-attr">delay</span>=<span class="hljs-string">{2000}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Block</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"Block #3"</span> <span class="hljs-attr">delay</span>=<span class="hljs-string">{3000}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Block</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"Block #4"</span> <span class="hljs-attr">delay</span>=<span class="hljs-string">{4000}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Block</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"Block #5"</span> <span class="hljs-attr">delay</span>=<span class="hljs-string">{5000}</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>The <code>&lt;Block/&gt;</code> component receives a <code>text</code> and a <code>delay</code> prop. <code>delay</code> represents how long to wait before rendering its template, that is simulating some network request call.</p>
<p>Here’s the <code>&lt;Block/&gt;</code> component:</p>
<pre><code class="lang-js">{<span class="hljs-comment">/** 📂 src/components/Block.astro **/</span>}
---
<span class="hljs-keyword">import</span> { sleep } <span class="hljs-keyword">from</span> <span class="hljs-string">"../sleep"</span>;

interface Props {
  <span class="hljs-attr">text</span>: string;
  delay: number;
}

<span class="hljs-keyword">const</span> { text, delay } = Astro.props;

<span class="hljs-keyword">await</span> sleep(delay);
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
  {text}
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">style</span>&gt;</span><span class="css">
  <span class="hljs-selector-tag">div</span> {
    <span class="hljs-attribute">margin</span>: <span class="hljs-number">1rem</span> <span class="hljs-number">0</span>;
    <span class="hljs-attribute">padding</span>: <span class="hljs-number">2rem</span> <span class="hljs-number">6rem</span>;
    <span class="hljs-attribute">border-radius</span>: <span class="hljs-number">10px</span>;
    <span class="hljs-attribute">background-color</span>: blanchedalmond;
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">style</span>&gt;</span></span>
</code></pre>
<p>Where <code>sleep</code> is a utility as follows:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/sleep.ts </span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> sleep = <span class="hljs-function">(<span class="hljs-params">delay: number</span>) =&gt;</span>
  <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>(<span class="hljs-function">(<span class="hljs-params">r</span>) =&gt;</span> <span class="hljs-built_in">setTimeout</span>(r, delay));
</code></pre>
<p>Now, go to the Chrome browser and visit the <code>/streaming</code> route to view the wonders of streaming.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-26-at-11.47.56.png" alt="Initial block streamed while awaiting Block #2" width="1229" height="818" loading="lazy">
<em>Initial block streamed while awaiting Block #2</em></p>
<p>Each block of content comes in one at a time.</p>
<p>It’s important to note that we don’t have to abstract the async bits into components. Streaming equally works with standard promises within the Astro template:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/streaming_blocks</span>
---
<span class="hljs-keyword">import</span> Block <span class="hljs-keyword">from</span> <span class="hljs-string">"../components/Block.astro"</span>;
<span class="hljs-keyword">import</span> { sleep } <span class="hljs-keyword">from</span> <span class="hljs-string">"../sleep"</span>;

<span class="hljs-keyword">const</span> block5Promise = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> sleep(<span class="hljs-number">1000</span>);
  <span class="hljs-keyword">return</span> <span class="hljs-string">"Block #5"</span>;
};
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Streaming<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Block</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"Block #1"</span> <span class="hljs-attr">delay</span>=<span class="hljs-string">{1000}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Block</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"Block #2"</span> <span class="hljs-attr">delay</span>=<span class="hljs-string">{2000}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Block</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"Block #3"</span> <span class="hljs-attr">delay</span>=<span class="hljs-string">{3000}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Block</span> <span class="hljs-attr">text</span>=<span class="hljs-string">"Block #4"</span> <span class="hljs-attr">delay</span>=<span class="hljs-string">{4000}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{block5Promise}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>An important fact to note here is that Astro initiates the async fetches in parallel when sibling async components are in the component tree.</p>
<p>So in our example, <code>Block #1</code> through <code>Block #5</code> start fetching data in parallel and don’t block one another.</p>
<p>When <code>Block #4</code> is rendered, <code>block5Promise</code> is already fetched as it takes one second compared to <code>Block #4</code>’s four seconds. So the result of <code>block5</code> is streamed alongside <code>Block #4</code>.</p>
<p>This can be difficult to grasp via text descriptions, so here's a visual:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-25-at-13.44.47@2x.png" alt="Describing the parallelized rendering of each block." width="1476" height="1076" loading="lazy">
<em>Describing the parallelized rendering of each block.</em></p>
<p>Give this a look in your Chrome browser.</p>
<h3 id="heading-how-to-take-advantage-of-streaming">How to take advantage of streaming</h3>
<p>Since Astro supports streaming by default, understanding and applying it is the first step to taking advantage of streaming.</p>
<p>Consider the following example:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> { sleep } <span class="hljs-keyword">from</span> <span class="hljs-string">"../sleep"</span>;

<span class="hljs-keyword">const</span> getSomeData = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> sleep(<span class="hljs-number">1000</span>);
  <span class="hljs-keyword">return</span> <span class="hljs-string">"some data "</span>;
};

<span class="hljs-keyword">const</span> getSomeOtherData = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> sleep(<span class="hljs-number">200</span>);
  <span class="hljs-keyword">return</span> <span class="hljs-string">"another data"</span>;
};

<span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> getSomeData();
<span class="hljs-keyword">const</span> otherData = <span class="hljs-keyword">await</span> getSomeOtherData();
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Product<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>A name<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{data}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>A fact<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{otherData}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>In the example above, we presumably need to fetch two resources, <code>data</code> and <code>otherData</code>. But our solution blocks streaming. We wait for <code>await getSomeData()</code> and <code>await getSomeOtherData()</code> before sending the full page to the browser.</p>
<p>If we wanted to take advantage of server streaming, we could either render the promises directly within the markup:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> { sleep } <span class="hljs-keyword">from</span> <span class="hljs-string">"../sleep"</span>;

<span class="hljs-keyword">const</span> getSomeData = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> sleep(<span class="hljs-number">1000</span>);
  <span class="hljs-keyword">return</span> <span class="hljs-string">"some data "</span>;
};

<span class="hljs-keyword">const</span> getSomeOtherData = <span class="hljs-keyword">async</span> () =&gt; {
  <span class="hljs-keyword">await</span> sleep(<span class="hljs-number">200</span>);
  <span class="hljs-keyword">return</span> <span class="hljs-string">"another data"</span>;
};
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Product<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>A name<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{getSomeData}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>A fact<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">p</span>&gt;</span>{getSomeOtherData}<span class="hljs-tag">&lt;/<span class="hljs-name">p</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>Or extract the data fetching to child components:</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">import</span> Data <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/Data.astro'</span>
<span class="hljs-keyword">import</span> OtherData <span class="hljs-keyword">from</span> <span class="hljs-string">'../components/OtherData.astro'</span>
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Product<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>A name<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Handle fetch of data in &lt;Data /&gt; --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">Data</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h2</span>&gt;</span>A fact<span class="hljs-tag">&lt;/<span class="hljs-name">h2</span>&gt;</span>
    <span class="hljs-comment">&lt;!-- Handle other data fetch in &lt;OtherData /&gt; --&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">OtherData</span> /&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>Excellent!</p>
<h2 id="heading-wrapping-up-this-chapter-5">Wrapping Up This Chapter</h2>
<p>Server-side rendering is powerful and opens up many opportunities in our application. But with much power comes responsibility. </p>
<p>So, before considering making every page in your application server-rendered, consider the pros and cons (as discussed in Chapter 3). Then, make the right decision for your application — that’s where true responsibility lies. And do not forget to leverage hybrid rendering where possible.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-139.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chapter seven.</em></p>
<h1 id="heading-chapter-7-be-audible-how-to-build-a-fullstack-astro-project">Chapter 7: Be Audible! (How to Build a Fullstack Astro Project)</h1>
<blockquote>
<p>… People will believe what they see. Let them see. ― Henry David Thoreau</p>
</blockquote>
<p>In this chapter, I’ll ask you to see beyond static apps and build a full stack application with Astro. To view the complete application, see the <a target="_blank" href="https://github.com/understanding-astro/react.dev-astrohttps://github.com/understanding-astro/fullstack-astro">GitHub repo</a>. </p>
<h2 id="heading-what-youll-learn-6">What You’ll Learn</h2>
<ul>
<li>The ability to add authentication to an Astro application.</li>
<li>An understanding of setting up a backend for an Astro application.</li>
<li>A working knowledge of handling form submissions without dedicated API routes.</li>
<li>Hands-on experience uploading and retrieving data in an Astro application.</li>
<li>An understanding of the kind of apps you can build with Astro.</li>
</ul>
<h2 id="heading-project-setup">Project Setup</h2>
<p>We’ve seen how to build static sites with Astro. So, to make this section laser-focused on scripting and Astro features, I’ve set up a static site for us to work on here.</p>
<p>The site has been stripped of any relevant functionality. We will build those step-by-step together.</p>
<p>Start by cloning the project:</p>
<pre><code class="lang-bash">git <span class="hljs-built_in">clone</span> https://github.com/understanding-astro/fullstack-astro
</code></pre>
<p>Change directories:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> fullstack-astro
</code></pre>
<p>You should be on the <code>clean-slate</code> branch by default. Otherwise, check out to <code>clean-slate</code>.</p>
<p>Next, install dependencies and start the application:</p>
<pre><code class="lang-bash">npm install &amp;&amp; npm run start
</code></pre>
<p>The application should successfully run on one of the local server ports.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-11.59.17@2x.png" alt="The BeAudible app initialised. " width="2580" height="1489" loading="lazy">
<em>The BeAudible app initialised.</em></p>
<h2 id="heading-project-overview-1">Project Overview</h2>
<p>Our application is for a hypothetical startup, BeAudible. Its mission is to discover the voices of the world.</p>
<p>In technical terms, BeAudible lets authorised users create audio recordings, upload them to their servers, and have a timeline where people can listen to everyone’s recordings.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/beaudible-overview.png" alt="An overview of the BeAudible application." width="909" height="462" loading="lazy">
<em>An overview of the BeAudible application.</em></p>
<p>The project we just cloned will receive and upload a user’s recording and eventually display every recording on a shared timeline.</p>
<p>Let’s explore the pages in the project.</p>
<h3 id="heading-the-homepage">The homepage</h3>
<p>Firstly, consider the homepage, that is the base route <code>/</code>.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-11.59.17@2x-1.png" alt="The sections of the BeAudible application." width="2580" height="1489" loading="lazy">
<em>The sections of the BeAudible application.</em></p>
<ol>
<li>The navigation bar holds a feedback form for users to send their thoughts.</li>
<li>The navigation bar includes a record link to navigate to a dedicated page for recording a user’s audio.</li>
<li>The navigation bar contains a sign-out button. By implication, the homepage should be protected, that is only authenticated users should land here.</li>
<li>Finally, in the centre of the page lies the timeline that should list all users’ recordings.</li>
</ol>
<h3 id="heading-the-record-page">The record page</h3>
<p>If you click “Record” from the navigation bar, you will be navigated to the <code>/record</code> route where a user can record their audio.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-12.24.30.png" alt="The record page." width="1266" height="777" loading="lazy">
<em>The record page.</em></p>
<p>A React component hydrated in the Astro application powers the recording user interface element.</p>
<h3 id="heading-the-signup-page">The signup page</h3>
<p>Now, go to the <code>/signup</code> route.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-12.22.45.png" alt="The sign up page." width="1177" height="763" loading="lazy">
<em>The sign-up page.</em></p>
<p>This is the page to sign up users to BeAudible.</p>
<h3 id="heading-the-sign-in-page">The sign-in page</h3>
<p>Finally, visit the <code>/signin</code> route.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-12.21.59.png" alt="The signin page." width="1234" height="765" loading="lazy">
<em>The sign-in page.</em></p>
<p>This is the page for previously authenticated users to log in to the application.</p>
<p>Go ahead and kill the running application from the terminal. Then, we’ll continue with some setup.</p>
<h3 id="heading-helper-components-and-utilities">Helper components and utilities</h3>
<p>To ensure our focus remains on Astro, I created UI components and stored them in the <code>src/components</code> folder.</p>
<p>We will import and use these components to develop our solution as we proceed.</p>
<p>Similarly, constants have been stored in <code>src/constants</code> and utility scripts in <code>src/scripts</code>. We aim to concentrate on the critical objective of this chapter, which is to build a full stack application with Astro.</p>
<h2 id="heading-technology-choices">Technology Choices</h2>
<ol>
<li><strong>Firebase</strong> as a backend service: we can choose any backend service with Astro, but we’ll use Firebase for simplicity. The principles we’ll discuss work with any other preferred service. We will leverage Firebase’s authentication and cloud storage services.</li>
<li><strong>Tailwind</strong> for styling: Tailwind is famous for styling applications. Instead of writing the styles manually, the project uses Tailwind.</li>
<li><strong>Astro</strong> as the primary web framework: Of course, the web framework of choice for our application is Astro. No questions asked! But we will also leverage React components for islands of interactivity.</li>
</ol>
<h2 id="heading-backend-setup">Backend Setup</h2>
<p>Let’s point our attention to setting up our backend server. Remember, we will use Firebase as our backend service.</p>
<p>Go to the <a target="_blank" href="https://www.freecodecamp.org/news/p/3c1efa5a-f575-4365-9958-d220b339bc38/[https://firebase.google.com/]">Firebase homepage</a> and visit the Firebase console.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-12.35.06@2x.png" alt="The Firebase homepage. " width="2000" height="956" loading="lazy">
<em>The Firebase homepage.</em></p>
<p>The process is much smoother if you have (and are signed in to) a Google account (for example, Gmail).</p>
<p>Next, create a new Firebase project.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-12.36.54@2x.png" alt="Creating a new Firebase project." width="2000" height="912" loading="lazy">
<em>Creating a new Firebase project.</em></p>
<p>Name the project <code>BeAudible</code> and choose whether to use Google Analytics in the project.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-12.41.10@2x.png" alt="Choosing Google analytics and creating the project." width="2000" height="1311" loading="lazy">
<em>Choosing Google analytics and creating the project.</em></p>
<p>After successfully creating the project, add a web application to the Firebase project.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-12.51.18@2x.png" alt="Adding a web application to the Firebase project. " width="2366" height="1120" loading="lazy">
<em>Adding a web application to the Firebase project.</em></p>
<p>Now, continue the web app set-up process by choosing a name (preferably the same as before), setting up Firebase hosting, and registering the web application.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-12.53.46@2x.png" alt="Continuing the application set-up." width="2060" height="1639" loading="lazy">
<em>Continuing the application set-up.</em></p>
<p>The next step is critical.</p>
<p><strong>Copy your web app’s Firebase configuration</strong>. We’ll use that to initialise the Firebase application client side.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-12.59.41@2x.png" alt="Copying the Firebase configuration for the client SDK." width="2035" height="1543" loading="lazy">
<em>Copying the Firebase configuration for the client SDK.</em></p>
<p>The next steps are optional. Follow the guided prompt from Firebase and continue to the Firebase console.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-13.02.36@2x.png" alt="Following the guided prompt from Firebase." width="1620" height="1379" loading="lazy">
<em>Following the guided prompt from Firebase.</em></p>
<p>Upon completion, we’ll be redirected to the Firebase application dashboard.</p>
<p>Go to the project settings, find the service account section, and generate a new private key that we’ll leverage in our server application.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-27-at-11.26.30.png" alt="Project overview > Project settings " width="1203" height="291" loading="lazy">
<em>Project overview &gt; Project settings</em></p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-27-at-11.28.49.png" alt="Generating a new private key. " width="1016" height="876" loading="lazy">
<em>Generating a new private key.</em></p>
<p>This will download a JSON file to your machine. Keep it secure as it provides access to Firebase’s service. We will leverage this to access Firebase’s server resources from our application server.</p>
<h2 id="heading-how-to-handle-authentication">How to Handle Authentication</h2>
<p>Generally speaking, authentication is serious business and can take different forms.</p>
<p>Firebase provides an authentication service, so we will leverage its client libraries to authenticate the user client-side.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/simple-auth-flow.png" alt="Simplified authentication process." width="567" height="190" loading="lazy">
<em>Simplified authentication process.</em></p>
<p>The client authentication will communicate with Firebase’s servers, but later on, we will look at verifying a user’s authentication token (JWT) on our server.</p>
<p>First, set up the Firebase application to receive client authentication requests.</p>
<p>Return to the Firebase console and set up authentication.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-15.13.50@2x.png" alt="Select authentication from the list of provided services." width="2000" height="1152" loading="lazy">
<em>Select authentication from the list of provided services.</em></p>
<p>Firebase provides different sign-in methods. Let’s keep this simple. Enable the Email and password method from the Firebase console.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-15.15.36@2x.png" alt="Selecting the email / password sign-in method." width="2186" height="1332" loading="lazy">
<em>Selecting the email / password sign-in method.</em></p>
<p>Make sure to enable the option and hit save.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-15.16.33@2x.png" alt="Enabling and saving the Email / Password sign-in method." width="2134" height="1022" loading="lazy">
<em>Enabling and saving the Email / Password sign-in method.</em></p>
<h3 id="heading-how-to-initialise-firebase-on-the-client">How to initialise Firebase on the client</h3>
<p><code>src/scripts/firebase/init.ts</code> contains the initialisation script for our client application.</p>
<p>The code responsible for initialising the application is shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ...</span>
<span class="hljs-comment">// 📂 src/scripts/firebase/init.ts</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> app = initializeApp(firebaseConfig);
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> auth = getAuth(app);
</code></pre>
<p>The script exports the initialised application via <code>app</code> and the authentication client module via <code>auth</code> where <code>initializeApp</code> and <code>getAuth</code> are methods imported from the Firebase SDK.</p>
<p>We must now replace the <code>firebaseConfig</code> variable with the object copied while initialising the Firebase application.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-12.59.41@2x-1.png" alt="The firebase client configuration. " width="2035" height="1543" loading="lazy">
<em>The firebase client configuration.</em></p>
<p>Once this is done, we should have the Firebase client rightly initialised.</p>
<h3 id="heading-how-to-use-the-firebase-emulators">How to use the Firebase emulators</h3>
<p>Talking to the production firebase services while testing and developing locally is rather silly.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/talk-to-prod-firebase.png" alt="Sending requests to the production Firebase servers while developing locally. " width="1163" height="389" loading="lazy">
<em>Sending requests to the production Firebase servers while developing locally.</em></p>
<p>Instead, we can use the Firebase Emulator Suite while developing locally. The emulator suite will intercept our Firebase service requests and provide a testing ground locally without hitting the production services.</p>
<p>I’ve set up the project to use the Firebase emulators. So let’s get it running.</p>
<p>Make sure you have the Firebase CLI tools installed. If you don’t, install the CLI via the following command:</p>
<pre><code class="lang-bash">npm install -g firebase-tools
</code></pre>
<p>Assuming you have the application running in one tab of your terminal, open another tab and run the firebase <code>emulators</code> script to start the firebase emulators:</p>
<pre><code class="lang-bash">npm run emulators
</code></pre>
<p>This will start the authentication and storage emulators with a user interface running on <code>localhost:4001</code>. We can view the development data in the emulator user interface, for example application user signups and uploaded recordings.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-15.06.19.png" alt="Starting the Firebase emulators. " width="841" height="752" loading="lazy">
<em>Starting the Firebase emulators.</em></p>
<h3 id="heading-how-to-handle-user-signups">How to handle user signups</h3>
<p>So, how are we going to handle user signups?</p>
<p>Please consider the overall flow diagram below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/sign-up-flow.png" alt="The signup flow." width="1835" height="2647" loading="lazy">
<em>The signup flow.</em></p>
<ul>
<li>The flow kicks off with the user submitting the signup form.</li>
<li>Then check if the submitted email and password are valid.</li>
<li>If the form values are invalid, display an error.</li>
<li>Create a new user via the <code>createUserWithEmailAndPassword</code> method of the Firebase auth module.</li>
<li>If the new user creation fails, display an error.</li>
<li>Otherwise, our new user is now in a signed-in state.</li>
<li>Grab the user auth token (this is called ID token in Firebase lingo and represents a JSON Web Token (JWT)).</li>
<li>Redirect the user to the homepage with the token as a URL parameter, that is <code>/?token=${USER_AUTH_TOKEN}</code>.</li>
</ul>
<p>Before delving into the code for how to do this, I’d like to point out that the project has module aliasing set up to prevent pesky relative imports, for example:</p>
<pre><code class="lang-js"><span class="hljs-comment">// This ... </span>
<span class="hljs-keyword">import</span> { auth } <span class="hljs-keyword">from</span> <span class="hljs-string">"../../firebase/init"</span>

<span class="hljs-comment">// Becomes this ...</span>
<span class="hljs-keyword">import</span> { auth } <span class="hljs-keyword">from</span> <span class="hljs-string">"@scripts/firebase/init"</span>;
</code></pre>
<p>This is achieved by updating the <code>tsconfig.json</code> file to include the alias:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 tsconfig.json</span>
{
   <span class="hljs-comment">// ...</span>
    <span class="hljs-string">"baseUrl"</span>: <span class="hljs-string">"."</span>,
    <span class="hljs-string">"paths"</span>: {
      <span class="hljs-string">"@components/*"</span>: [<span class="hljs-string">"src/components/*"</span>],
      <span class="hljs-string">"@layouts/*"</span>: [<span class="hljs-string">"src/layouts/*"</span>],
      <span class="hljs-string">"@scripts/*"</span>: [<span class="hljs-string">"src/scripts/*"</span>],
      <span class="hljs-string">"@stores/*"</span>: [<span class="hljs-string">"src/stores/*"</span>],
      <span class="hljs-string">"@constants/*"</span>: [<span class="hljs-string">"src/constants/*"</span>]
    }
  }
}
</code></pre>
<p>We will reference existing modules in the project via the relevant module alias.</p>
<p>Now, here is the annotated code for handling the user sign-up:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/pages/signup.astro --&gt;</span> 
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-comment">// import the Validator from the tiny "validator.tool" library </span>
  <span class="hljs-keyword">import</span> Validator <span class="hljs-keyword">from</span> <span class="hljs-string">"validator.tool"</span>;
  <span class="hljs-keyword">import</span> { createUserWithEmailAndPassword } <span class="hljs-keyword">from</span> <span class="hljs-string">"firebase/auth"</span>;
  <span class="hljs-comment">// Import the auth module from `src/scripts` </span>
  <span class="hljs-keyword">import</span> { auth } <span class="hljs-keyword">from</span> <span class="hljs-string">"@scripts/firebase/init"</span>;
  <span class="hljs-comment">// Import basic form validation rules </span>
  <span class="hljs-keyword">import</span> { authClientValidationRules } <span class="hljs-keyword">from</span> <span class="hljs-string">"@scripts/authClientValidationRules"</span>;

 <span class="hljs-comment">// Type alias for the form values </span>
  type FormValues = {
    email?: string;
    password?: string;
  };

  <span class="hljs-comment">// Grab the submit button element </span>
  <span class="hljs-keyword">const</span> submitButton = <span class="hljs-built_in">document</span>.getElementById(
    <span class="hljs-string">"submit-signup-form"</span>
  ) <span class="hljs-keyword">as</span> HTMLButtonElement | <span class="hljs-literal">null</span>;

  <span class="hljs-comment">// Grab the form element </span>
  <span class="hljs-keyword">const</span> form = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"signup-form"</span>) <span class="hljs-keyword">as</span> HTMLFormElement | <span class="hljs-literal">null</span>;

   <span class="hljs-comment">// Initialise the validator </span>
  <span class="hljs-keyword">const</span> validator = <span class="hljs-keyword">new</span> Validator({
    form,
    <span class="hljs-comment">// Pass in basic rules already existing in the project</span>
    <span class="hljs-attr">rules</span>: authClientValidationRules,
  });


  <span class="hljs-keyword">if</span> (validator.form) {
    <span class="hljs-comment">// Attach a submit event handler on the form</span>
    validator.form.onsubmit = <span class="hljs-keyword">async</span> (evt) =&gt; {
      evt.preventDefault();

      <span class="hljs-keyword">const</span> errors = validator.errorMessages;
      <span class="hljs-keyword">const</span> values = validator.getValues() <span class="hljs-keyword">as</span> FormValues;

      <span class="hljs-comment">//Check for errors </span>
      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Object</span>.keys(errors).length &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">const</span> errorMessages = <span class="hljs-built_in">Object</span>.values(errors).join(<span class="hljs-string">"...and..."</span>);
        <span class="hljs-keyword">return</span> alert(errorMessages);
      }

      <span class="hljs-keyword">const</span> { email, password } = values <span class="hljs-keyword">as</span> Required&lt;FormValues&gt;;

      <span class="hljs-keyword">if</span> (!submitButton) {
        <span class="hljs-keyword">return</span> alert(<span class="hljs-string">"Missing form button"</span>);
      }

      <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// Show submitting state </span>
        submitButton.innerText = <span class="hljs-string">"Submitting"</span>;
        submitButton.disabled = <span class="hljs-literal">true</span>;

        <span class="hljs-comment">// Create the new user </span>
        <span class="hljs-keyword">const</span> { user } = <span class="hljs-keyword">await</span> createUserWithEmailAndPassword(
          auth,
          email,
          password
        );

         <span class="hljs-comment">// redirect the user to the homepage with their token</span>
        <span class="hljs-keyword">const</span> token = <span class="hljs-keyword">await</span> user.getIdToken();
        <span class="hljs-built_in">window</span>.location.href = <span class="hljs-string">`/?token=<span class="hljs-subst">${token}</span>`</span>;
      } <span class="hljs-keyword">catch</span> (error) {
        submitButton.innerText = <span class="hljs-string">"Signup"</span>;
        submitButton.disabled = <span class="hljs-literal">false</span>;

        alert(error);
      }
    };
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>In the solution above, we’re handling form validation via <a target="_blank" href="https://github.com/jaywcjlove/validator.js">validator.js</a> but could have used any other library. Another minimal framework agnostic library that makes a good choice is <a target="_blank" href="https://github.com/pablo-abc/felte">Felte</a>.</p>
<h3 id="heading-how-to-handle-user-sign-in">How to handle user sign-in</h3>
<p>With user sign-up handled, the process for user sign-in is the same except for one change. Instead of calling the <code>createUserWithEmailAndPassword</code> method, we’ll use the <code>signInWithEmailAndPassword</code> Firebase auth method.</p>
<p>Notice how the flow is identical in the code below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/pages/signin.astro --&gt;</span>
<span class="hljs-comment">&lt;!-- ... --&gt;</span> 

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { signInWithEmailAndPassword } <span class="hljs-keyword">from</span> <span class="hljs-string">"firebase/auth"</span>;
  <span class="hljs-keyword">import</span> Validator <span class="hljs-keyword">from</span> <span class="hljs-string">"validator.tool"</span>;
  <span class="hljs-keyword">import</span> { auth } <span class="hljs-keyword">from</span> <span class="hljs-string">"@scripts/firebase/init"</span>;
  <span class="hljs-keyword">import</span> { authClientValidationRules } <span class="hljs-keyword">from</span> <span class="hljs-string">"@scripts/authClientValidationRules"</span>;

  type FormValues = {
    email?: string;
    password?: string;
  };

  <span class="hljs-keyword">const</span> form = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"signin-form"</span>) <span class="hljs-keyword">as</span> HTMLFormElement | <span class="hljs-literal">null</span>;
  <span class="hljs-keyword">const</span> submitButton = <span class="hljs-built_in">document</span>.querySelector(
    <span class="hljs-string">"#signin-form button[type='submit']"</span>
  ) <span class="hljs-keyword">as</span> HTMLButtonElement | <span class="hljs-literal">null</span>;

  <span class="hljs-keyword">const</span> validator = <span class="hljs-keyword">new</span> Validator({
    form,
    <span class="hljs-attr">rules</span>: authClientValidationRules,
  });

  <span class="hljs-keyword">if</span> (validator.form) {
    validator.form.onsubmit = <span class="hljs-keyword">async</span> (evt) =&gt; {
      evt.preventDefault();

      <span class="hljs-keyword">const</span> errors = validator.errorMessages;
      <span class="hljs-keyword">const</span> values = validator.getValues() <span class="hljs-keyword">as</span> FormValues;

      <span class="hljs-keyword">if</span> (<span class="hljs-built_in">Object</span>.keys(errors).length &gt; <span class="hljs-number">0</span>) {
        <span class="hljs-keyword">const</span> errorMessages = <span class="hljs-built_in">Object</span>.values(errors).join(<span class="hljs-string">"...and..."</span>);
        <span class="hljs-keyword">return</span> alert(errorMessages);
      }

      <span class="hljs-keyword">const</span> { email, password } = values <span class="hljs-keyword">as</span> Required&lt;FormValues&gt;;

      <span class="hljs-keyword">if</span> (!submitButton) {
        <span class="hljs-keyword">return</span> alert(<span class="hljs-string">"Missing form button"</span>);
      }

      <span class="hljs-keyword">try</span> {
        submitButton.innerText = <span class="hljs-string">"Submitting"</span>;
        submitButton.disabled = <span class="hljs-literal">true</span>;

        <span class="hljs-keyword">const</span> { user } = <span class="hljs-keyword">await</span> signInWithEmailAndPassword(
          auth,
          email,
          password
        );

        <span class="hljs-keyword">const</span> token = <span class="hljs-keyword">await</span> user.getIdToken();
        <span class="hljs-built_in">window</span>.location.href = <span class="hljs-string">`/?token=<span class="hljs-subst">${token}</span>`</span>;
      } <span class="hljs-keyword">catch</span> (error) {
        submitButton.innerText = <span class="hljs-string">"Signin"</span>;
        submitButton.disabled = <span class="hljs-literal">false</span>;

        alert(error);
      }
    };
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>With these in place, we’ve got authentication handled!</p>
<p>But a question that may remain in your heart is, why exactly are we sending the user token in the homepage redirect URL?</p>
<h2 id="heading-how-to-implement-protected-pages">How to Implement Protected Pages</h2>
<p>Every page in our application is statically generated except for <code>index.astro</code>, that is the homepage.</p>
<p>The homepage is server-side rendered because we want to ensure it’s protected, and that only authenticated users ever land here.</p>
<p>We will discuss how we’ll achieve this, but first we need to write some code that runs on the server here.</p>
<h3 id="heading-how-to-initialise-firebase-on-the-server">How to initialise Firebase on the server</h3>
<p>During the project initialisation, we downloaded a private key for server access. This is a JSON file in the form:</p>
<pre><code class="lang-js">{
  <span class="hljs-attr">type</span>: <span class="hljs-string">"..."</span>,
  <span class="hljs-attr">project_id</span>: <span class="hljs-string">"..."</span>
   <span class="hljs-comment">// more properties </span>
}
</code></pre>
<p>We need these values to initialise our server application. So, create a <code>.env</code> file to store these secrets. Then, we’ll break up the JSON keys into individual environment variables as shown below:</p>
<pre><code class="lang-js">
FIREBASE_PRIVATE_KEY_ID=<span class="hljs-string">"..."</span>
FIREBASE_PRIVATE_KEY=<span class="hljs-string">"..."</span>
FIREBASE_PROJECT_ID=<span class="hljs-string">"..."</span>
FIREBASE_CLIENT_EMAIL=<span class="hljs-string">"..."</span>
FIREBASE_CLIENT_ID=<span class="hljs-string">"..."</span>
FIREBASE_AUTH_URI=<span class="hljs-string">"..."</span>
FIREBASE_TOKEN_URI=<span class="hljs-string">"..."</span>
FIREBASE_AUTH_PROVIDER_CERT_URL=<span class="hljs-string">"..."</span>
FIREBASE_CLIENT_CERT_URL=<span class="hljs-string">"..."</span>
</code></pre>
<p>Save the <code>env</code> file. Without this, we won’t be able to access the application resources from our server.</p>
<p>✨ Fun fact: As discussed in Chapter 5, we’re providing TypeScript support for these environment values in <code>.env.d.ts</code>.</p>
<h3 id="heading-how-to-protect-the-home-page-route">How to protect the home page route</h3>
<p>Once a user has successfully signed in, Firebase generates a unique ID token that serves as their unique identifier and provides access to various resources, such as Firebase Cloud Storage.</p>
<p>I have loosely referred to this as auth tokens. We will use this ID token to recognise the user on our server.</p>
<p>✨ Fun fact: Firebase ID tokens are short-lived and last for an hour.</p>
<p>Consider the flow below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/protected-route-flow.png" alt="The protected route flow. " width="1488" height="1719" loading="lazy">
<em>The protected route flow.</em></p>
<ul>
<li>The flow kicks off with the user landing on the homepage.</li>
</ul>
<p>Note that the following steps are performed on the server, that is within the frontmatter section of our server-side rendered page.</p>
<ul>
<li>Then, retrieve the user ID token from the URL (first-time user) or the request cookies (returning user).</li>
<li>Verify the validity of the token. We will use the Firebase server SDK (Firebase admin) to check this.</li>
<li>If the token is invalid or doesn’t exist, the user is unauthorised. Redirect them to the <code>/signin</code> page.</li>
<li>If the token is valid, set the <code>token</code> as a cookie.</li>
</ul>
<p>✨Fun fact: by setting the token via cookies, we can remove the token from the URL and refresh without losing the user signed-in state. Every request will send back the cookie to the server, where we can recheck its validity.</p>
<p>Now, here’s the implementation:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>
---
<span class="hljs-comment">// ...</span>
<span class="hljs-keyword">import</span> { serverApp } <span class="hljs-keyword">from</span> <span class="hljs-string">"@scripts/firebase/initServer"</span>;
<span class="hljs-keyword">import</span> { getAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"firebase-admin/auth"</span>;
<span class="hljs-keyword">import</span> { TOKEN } <span class="hljs-keyword">from</span> <span class="hljs-string">"@constants/cookies"</span>;

<span class="hljs-comment">// Get client token from the URL param</span>
<span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(Astro.request.url);
<span class="hljs-keyword">const</span> urlTokenParam = url.searchParams.get(<span class="hljs-string">"token"</span>);

<span class="hljs-comment">// Get token from cookies </span>
<span class="hljs-keyword">const</span> cookieToken = Astro.cookies.get(TOKEN);
<span class="hljs-keyword">const</span> token = urlTokenParam || cookieToken.value;

<span class="hljs-keyword">if</span> (!token) {
  <span class="hljs-comment">// Unauthorised user. Redirect to sign in</span>
  <span class="hljs-keyword">return</span> Astro.redirect(<span class="hljs-string">"/signin"</span>);
}

<span class="hljs-keyword">const</span> auth = getAuth(serverApp);

<span class="hljs-keyword">try</span> {
  <span class="hljs-comment">// verify the auth token</span>
  <span class="hljs-keyword">await</span> auth.verifyIdToken(token);

  <span class="hljs-comment">// set token cookie </span>
  <span class="hljs-comment">// Note that the "TOKEN" constant refers to the string "X-Token."</span>
  Astro.cookies.set(TOKEN, token, {
    <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span>,
    <span class="hljs-attr">httpOnly</span>: <span class="hljs-literal">true</span>,
    <span class="hljs-attr">secure</span>: <span class="hljs-literal">true</span>,
  });
} <span class="hljs-keyword">catch</span> (error) {
  <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Could not decode token"</span>, {
    <span class="hljs-attr">fromCookie</span>: !!cookieToken.value,
    <span class="hljs-attr">fromUrl</span>: !!urlTokenParam,
  });

  <span class="hljs-comment">// Error occurred, e.g., invalid token. Redirect to sign in</span>
  <span class="hljs-keyword">return</span> Astro.redirect(<span class="hljs-string">"/signin"</span>);
}
---
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-15.41.52.png" alt="The token cookie set in the browser response." width="1275" height="892" loading="lazy">
<em>The token cookie set in the browser response.</em></p>
<h3 id="heading-how-to-update-the-redirect-url">How to update the redirect URL</h3>
<p>When a user successfully signs in, the user looks something like <code>localhost:3000/?token=${some-long-string}</code>.</p>
<p>After performing our token validation on the server and returning the protected <code>HTML</code> page, we may update the URL to remove the <code>token</code> parameter.</p>
<pre><code class="lang-js"><span class="hljs-comment">// Before </span>
<span class="hljs-attr">localhost</span>:<span class="hljs-number">3000</span>/?token=${some-long-string}

<span class="hljs-comment">// After </span>
<span class="hljs-attr">localhost</span>:<span class="hljs-number">3000</span>
</code></pre>
<p>This is not necessary, but a nice UX touch.</p>
<p>Since we want to do this on the client, our go-to solution is to add a client <code>&lt;script&gt;</code> to the page.</p>
<p>Consider the solution below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/pages/index.astro --&gt;</span> 
<span class="hljs-comment">&lt;!-- ... --&gt;</span> 

<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-comment">// Enhancement: remove the token from the URL after the page's parsed.</span>
  <span class="hljs-keyword">const</span> url = <span class="hljs-keyword">new</span> URL(<span class="hljs-built_in">window</span>.location.href);
  <span class="hljs-keyword">const</span> urlTokenParam = url.searchParams.get(<span class="hljs-string">"token"</span>);

  <span class="hljs-keyword">if</span> (urlTokenParam) {
    <span class="hljs-comment">// delete the token param from the URL</span>
    url.searchParams.delete(<span class="hljs-string">"token"</span>);

   <span class="hljs-comment">// update history without a refresh with the new URL</span>
    <span class="hljs-built_in">window</span>.history.pushState({}, <span class="hljs-string">""</span>, url.href);
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>The solution is arguably easy to reason about, with the crux after getting the search parameter being <code>window.history.pushState(...).</code></p>
<h3 id="heading-how-to-log-out-a-user-from-the-protected-page">How to log out a user from the protected page</h3>
<p>The top left section of the application’s navigation bar includes a sign-out button. When a user clicks this, we will sign them out of the application.</p>
<p>To sign out a user, we will use the Firebase client SDK to log a user out of the device.</p>
<p>But remember that the protected index page checks the <code>token</code> request cookie value.</p>
<p>When we sign out a user using the Firebase client SDK, the issued client <code>token</code> remains valid for up to an hour (depending on when it was issued).</p>
<p>So, consider the flow for our solution below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/sign-out-flow.png" alt="The user sign out flow." width="654" height="1262" loading="lazy">
<em>The user sign out flow (Click sign-out button, make a request to API endpoint, log out the user, re-ditrect user to sign-in page)</em></p>
<p>Let’s start our implementation by updating the client application to handle the click event on the sign-out button and initiate our flow as shown below:</p>
<pre><code class="lang-html"><span class="hljs-comment">&lt;!-- 📂 src/pages/layouts/BaseLayout.astro --&gt;</span> 
<span class="hljs-comment">&lt;!-- ... --&gt;</span>
<span class="hljs-tag">&lt;<span class="hljs-name">script</span>&gt;</span><span class="javascript">
  <span class="hljs-keyword">import</span> { auth } <span class="hljs-keyword">from</span> <span class="hljs-string">"@scripts/firebase/init"</span>;

   <span class="hljs-comment">// Grab the sign-out button </span>
  <span class="hljs-keyword">const</span> signoutButton = <span class="hljs-built_in">document</span>.getElementById(<span class="hljs-string">"sign-out-button"</span>) <span class="hljs-keyword">as</span>
    | HTMLButtonElement
    | <span class="hljs-literal">undefined</span>;

  <span class="hljs-keyword">if</span> (signoutButton) {
    <span class="hljs-comment">// Add a click event listener on the button</span>
    signoutButton.addEventListener(<span class="hljs-string">"click"</span>, <span class="hljs-keyword">async</span> () =&gt; {
      <span class="hljs-keyword">try</span> {
        <span class="hljs-comment">// Disable the button while we log the user out</span>
        signoutButton.disabled = <span class="hljs-literal">true</span>;
        <span class="hljs-comment">// Change button text to read "Signing out ..."</span>
        signoutButton.innerText = <span class="hljs-string">"Signing out ..."</span>;
        <span class="hljs-comment">// Invalidate server http cookie</span>
        <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"/api/auth/signout"</span>, {
          <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
        });

        <span class="hljs-keyword">if</span> (!response.ok) {
          <span class="hljs-keyword">throw</span> <span class="hljs-keyword">new</span> <span class="hljs-built_in">Error</span>(<span class="hljs-string">"server signout failed"</span>);
        }
        <span class="hljs-comment">/**
         * sign the user out via the signOut method
        * on the Firebase auth module 
        */</span>    
        <span class="hljs-keyword">await</span> auth.signOut ();
        <span class="hljs-comment">// Redirect to the signin page </span>
        <span class="hljs-built_in">window</span>.location.href = <span class="hljs-string">"/signin"</span>;
      } <span class="hljs-keyword">catch</span> (error) {
        signoutButton.disabled = <span class="hljs-literal">false</span>;
        alert(error);
      }
    });
  }
</span><span class="hljs-tag">&lt;/<span class="hljs-name">script</span>&gt;</span>
</code></pre>
<p>We’re making a request to <code>/api/auth/signout</code>, but the API route does not exist.</p>
<p>Let’s change that with the following code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/api/auth/signout.ts</span>
<span class="hljs-comment">// ...</span>

<span class="hljs-keyword">import</span> { TOKEN } <span class="hljs-keyword">from</span> <span class="hljs-string">"@constants/cookies"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> post: APIRoute = <span class="hljs-function">(<span class="hljs-params">ctx</span>) =&gt;</span> {
  ctx.cookies.delete(TOKEN, {
    <span class="hljs-attr">path</span>: <span class="hljs-string">"/"</span>,
  });

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({ <span class="hljs-attr">message</span>: <span class="hljs-string">"successfully signed out"</span> }),
  };
};
</code></pre>
<p>After successful sign-out, attempt to visit the protected page <code>localhost:3000</code>, and you’ll be automatically redirected to <code>/sign</code>.</p>
<p>We’re now cooking with gas! 🔥</p>
<h2 id="heading-cloud-storage-setup">Cloud Storage Setup</h2>
<p>We’ve got a big part of our application functioning — largely the authentication and keeping the index page protected. But we’re protecting an empty page at the moment. So users cannot record or view other users’ recordings.</p>
<p>Let’s fix this by setting up cloud storage to save user recordings on the server.</p>
<p>Go to the Firebase console and click “See all build features” to find the cloud storage service.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-15.33.40@2x.png" alt="Viewing all build features on the Firebase console." width="2182" height="1108" loading="lazy">
<em>Viewing all build features on the Firebase console.</em></p>
<p>Next, select the Storage service.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-15.33.58@2x.png" alt="Selecting the storage service. " width="2146" height="1459" loading="lazy">
<em>Selecting the storage service.</em></p>
<p>Then begin the setup.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-15.34.29@2x.png" alt="Clicking get started on the Storage service page." width="1988" height="845" loading="lazy">
<em>Clicking get started on the Storage service page.</em></p>
<p>Keep the storage rules as-is:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-15.34.40@2x.png" alt="The default storage rules. " width="1996" height="1350" loading="lazy">
<em>The default storage rules.</em></p>
<p>Then select a server location.</p>
<p>BeAudible is a hypothetical US startup, so I’ll choose a US location here.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-26-at-15.35.33@2x.png" alt="Selecting a Storage location." width="1892" height="1111" loading="lazy">
<em>Selecting a Storage location.</em></p>
<p>Once the setup is complete, visit the Storage page and copy the bucket name in the form <code>gs://{name-of-project}.appspot.com.</code></p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-27-at-16.43.07.png" alt="The Storage bucket name." width="1258" height="467" loading="lazy">
<em>The Storage bucket name.</em></p>
<p>Excellent!</p>
<p>When we upload and get the user recordings, we’ll need this to connect to the storage servers.</p>
<h2 id="heading-how-to-upload-audio-recordings">How to Upload Audio Recordings</h2>
<p>The recorder user interface is powered by a React Recorder component hydrated via the <code>client:load</code> directive.</p>
<pre><code class="lang-js">&lt;Recorder client:load&gt;
   ...
&lt;/Recorder&gt;
</code></pre>
<p>Open the <code>Recorder</code> component and consider the <code>onAudioDownload</code> callback.</p>
<pre><code class="lang-js"><span class="hljs-comment">// src/components/AudioRecorder.tsx</span>
<span class="hljs-comment">// ... </span>
&lt;VoiceRecorder
   onAudioDownload={<span class="hljs-function">(<span class="hljs-params">blob: Blob</span>) =&gt;</span> {
   <span class="hljs-comment">// 👀 upload recording</span>
   }}
/&gt;
</code></pre>
<p>After a user completes the recording, this callback will be invoked. Our first task is to go ahead and upload the audio blob to the server.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/upload-flow.png" alt="Sending audio blob to a server endpoint." width="1288" height="331" loading="lazy">
<em>Sending audio blob to a server endpoint.</em></p>
<h3 id="heading-how-to-handle-uploads-via-an-api-route">How to handle uploads via an API route</h3>
<p>Let’s go ahead and create the API endpoint that’ll receive the audio blob from the client.</p>
<p>Consider the flow for our solution below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/save-audio-recording-flow.png" alt="The save recording endpoint flow diagram." width="801" height="908" loading="lazy">
<em>The save recording endpoint flow diagram (Endpoint receives post rquest. Is token valid? If yes, convert audio blob to buffer, save file to storage with unique name, and return success response. If not, return error response.</em></p>
<p>Now, here’s the annotated code:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/api/recording.ts</span>
<span class="hljs-comment">// ... </span>
<span class="hljs-keyword">import</span> type { APIRoute } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;

<span class="hljs-comment">// nanoid will be used to generate unique IDs</span>
<span class="hljs-keyword">import</span> { nanoid } <span class="hljs-keyword">from</span> <span class="hljs-string">"nanoid"</span>;
<span class="hljs-keyword">import</span> { TOKEN } <span class="hljs-keyword">from</span> <span class="hljs-string">"@constants/cookies"</span>;
<span class="hljs-keyword">import</span> { getAuth } <span class="hljs-keyword">from</span> <span class="hljs-string">"firebase-admin/auth"</span>;
<span class="hljs-keyword">import</span> { BUCKET_NAME } <span class="hljs-keyword">from</span> <span class="hljs-string">"@constants/firebase"</span>;
<span class="hljs-keyword">import</span> { getStorage } <span class="hljs-keyword">from</span> <span class="hljs-string">"firebase-admin/storage"</span>;
<span class="hljs-keyword">import</span> { serverApp } <span class="hljs-keyword">from</span> <span class="hljs-string">"@scripts/firebase/initServer"</span>;

<span class="hljs-comment">// get firebase server auth module </span>
<span class="hljs-keyword">const</span> auth = getAuth(serverApp);

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> post: APIRoute = <span class="hljs-keyword">async</span> (ctx) =&gt; {
  <span class="hljs-comment">// Create an error response </span>
  <span class="hljs-keyword">const</span> authUserError = <span class="hljs-keyword">new</span> Response(<span class="hljs-string">"Unauthenticated user"</span>, { <span class="hljs-attr">status</span>: <span class="hljs-number">401</span> });

  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Get token cookie </span>
    <span class="hljs-keyword">const</span> authToken = ctx.cookies.get(TOKEN).value;

    <span class="hljs-comment">// not present, return error response </span>
    <span class="hljs-keyword">if</span> (!authToken) {
      <span class="hljs-keyword">return</span> authUserError;
    }

    <span class="hljs-comment">// verify the user token</span>
    <span class="hljs-keyword">await</span> auth.verifyIdToken(authToken);    
  } <span class="hljs-keyword">catch</span> (error) {
   <span class="hljs-comment">/**
     * Return error response, e.g., 
      * if the token verification fails
     */</span>
    <span class="hljs-keyword">return</span> authUserError;
  }

  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Get the audio blob from the client request</span>
    <span class="hljs-keyword">const</span> blob = <span class="hljs-keyword">await</span> ctx.request.blob();

    <span class="hljs-comment">// Get access to the firebase storage </span>
    <span class="hljs-keyword">const</span> storage = getStorage(serverApp);
    <span class="hljs-keyword">const</span> bucket = storage.bucket(BUCKET_NAME);

    <span class="hljs-comment">// convert Blob to native Node Buffer for server storage</span>
    <span class="hljs-keyword">const</span> buffer = Buffer.from(<span class="hljs-keyword">await</span> blob.arrayBuffer());
    <span class="hljs-keyword">const</span> file = bucket.file(<span class="hljs-string">`recording-<span class="hljs-subst">${nanoid()}</span>.wav`</span>);

    <span class="hljs-comment">// save to firebase storage </span>
    <span class="hljs-keyword">await</span> file.save(buffer);

    <span class="hljs-comment">// return a successful response</span>
    <span class="hljs-keyword">return</span> {
      <span class="hljs-attr">body</span>: <span class="hljs-built_in">JSON</span>.stringify({
        <span class="hljs-attr">message</span>: <span class="hljs-string">"Recording uploaded"</span>,
      }),
    };
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
    <span class="hljs-keyword">return</span> <span class="hljs-keyword">new</span> Response(<span class="hljs-string">"Something went horribly wrong"</span>, { <span class="hljs-attr">status</span>: <span class="hljs-number">500</span> });
  }
};
<span class="hljs-comment">// ...</span>
</code></pre>
<h3 id="heading-how-to-upload-recordings-from-the-client">How to upload recordings from the client</h3>
<p>Now that we’ve got the API endpoint ready to receive client requests, let’s go ahead and upload the user recordings from the client.</p>
<p>Instead of clogging our user interface components with the upload logic, I find it more maintainable to move such business logic away from the UI components and, in our case, have this collocated with the application state managed via <code>nanastores</code>.</p>
<p>Remember <code>nanostores</code>?</p>
<p>We’ll use <a target="_blank" href="https://github.com/nanostores/nanostores">nano stores</a> for state management. The <code>~1kb</code> library is simple and efficient for our use case.</p>
<p>Create a new <code>audioRecording.ts</code> file to handle our recording state and also be responsible for exposing a <code>uploadRecording</code> method.</p>
<p>Consider the implementation below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/stores/audioRecording.ts</span>
<span class="hljs-keyword">import</span> { atom } <span class="hljs-keyword">from</span> <span class="hljs-string">"nanostores"</span>;

<span class="hljs-comment">/**
 * Deterministic state representation
 */</span>
type Store =
  | {
      <span class="hljs-attr">blob</span>: <span class="hljs-literal">null</span>;
      status: <span class="hljs-string">"idle"</span>;
    }
  | {
      <span class="hljs-attr">blob</span>: Blob;
      status: <span class="hljs-string">"uploading"</span> | <span class="hljs-string">"completed"</span> | <span class="hljs-string">"failed"</span>;
    };

<span class="hljs-comment">/**
 * Optional naming convention: $[name_of_store]
 * instead of [name_of_store]Store
 *, i.e., $audioRecording instead of audioRecordingStore
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> $audioRecording = atom&lt;Store&gt;({
  <span class="hljs-comment">// Initialise the atom with the default state </span>
  <span class="hljs-attr">blob</span>: <span class="hljs-literal">null</span>,
  <span class="hljs-attr">status</span>: <span class="hljs-string">"idle"</span>,
});

<span class="hljs-comment">/**
 * upload audio recording action
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> uploadRecording = <span class="hljs-keyword">async</span> (blob: Blob) =&gt; {
  <span class="hljs-comment">// Update $audioRecording state to "uploading."</span>
  $audioRecording.set({
    <span class="hljs-attr">status</span>: <span class="hljs-string">"uploading"</span>,
    blob,
  });

  <span class="hljs-keyword">try</span> {
   <span class="hljs-comment">// POST request to our recording endpoint </span>
    <span class="hljs-keyword">const</span> response = <span class="hljs-keyword">await</span> fetch(<span class="hljs-string">"/api/recording"</span>, {
      <span class="hljs-attr">method</span>: <span class="hljs-string">"POST"</span>,
      <span class="hljs-attr">body</span>: blob, <span class="hljs-comment">// pass blob as the request body </span>
    });

    <span class="hljs-keyword">if</span> (response.ok) {
     <span class="hljs-comment">// Successful? Update state to "completed."</span>
      $audioRecording.set({
        <span class="hljs-attr">status</span>: <span class="hljs-string">"completed"</span>,
        blob,
      });
    } <span class="hljs-keyword">else</span> {
     <span class="hljs-comment">// Request failed. Update state to "failed."</span>
      $audioRecording.set({
        <span class="hljs-attr">status</span>: <span class="hljs-string">"failed"</span>,
        blob,
      });
    }
  } <span class="hljs-keyword">catch</span> (error) {
    $audioRecording.set({
      <span class="hljs-attr">status</span>: <span class="hljs-string">"failed"</span>,
      blob,
    });
  } <span class="hljs-keyword">finally</span> {
    <span class="hljs-comment">// after 't' revert state to idle again</span>
    <span class="hljs-keyword">const</span> timeout = <span class="hljs-number">3000</span>;
    <span class="hljs-built_in">setTimeout</span>(<span class="hljs-function">() =&gt;</span> {
      $audioRecording.set({
        <span class="hljs-attr">status</span>: <span class="hljs-string">"idle"</span>,
        <span class="hljs-attr">blob</span>: <span class="hljs-literal">null</span>,
      });
    }, timeout);
  }
};
</code></pre>
<p>Our UI state is well-represented, and the upload action is defined. But this will only take effect when used in the UI component.</p>
<h3 id="heading-how-to-react-to-ui-changes-in-framework-components">How to react to UI changes in framework components</h3>
<p>We will now update the <code>AudioRecorder</code> UI component to react to the state in the <code>$audioRecording</code> store as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/components/AudioRecorder.tsx</span>

<span class="hljs-comment">/**
* The useStore hook will help with the React 
* component rerenders. In simple terms, it'll hook into the 
* store and react upon any change.
*/</span>
<span class="hljs-keyword">import</span> { useStore } <span class="hljs-keyword">from</span> <span class="hljs-string">"@nanostores/react"</span>;
<span class="hljs-keyword">import</span> { VoiceRecorder } <span class="hljs-keyword">from</span> <span class="hljs-string">"react-voice-recorder-player"</span>;
<span class="hljs-comment">// Import the store and the upload recording action</span>
<span class="hljs-keyword">import</span> { $audioRecording, uploadRecording } <span class="hljs-keyword">from</span> <span class="hljs-string">"@stores/audioRecording"</span>;

type Props = {
  cta?: string;
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> Recorder = <span class="hljs-function">(<span class="hljs-params">props: Props</span>) =&gt;</span> {
  <span class="hljs-comment">// Get the current application state from the store </span>
  <span class="hljs-keyword">const</span> state = useStore($audioRecording);

  <span class="hljs-comment">// React deterministically based on the status of the store</span>
  <span class="hljs-keyword">switch</span> (state.status) {
    <span class="hljs-keyword">case</span> <span class="hljs-string">"idle"</span>:
      <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">VoiceRecorder</span>
               // 👀 <span class="hljs-attr">Invoke</span> <span class="hljs-attr">uploadRecording</span> <span class="hljs-attr">after</span> <span class="hljs-attr">a</span> <span class="hljs-attr">user</span> <span class="hljs-attr">completes</span> <span class="hljs-attr">the</span> <span class="hljs-attr">recording</span> 
            <span class="hljs-attr">onAudioDownload</span>=<span class="hljs-string">{(blob:</span> <span class="hljs-attr">Blob</span>) =&gt;</span> uploadRecording(blob)}
          /&gt;

          {props.cta}
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      );
<span class="hljs-comment">/** 
 Show relevant UI during the uploading state. 
**/</span>
    <span class="hljs-keyword">case</span> <span class="hljs-string">"uploading"</span>:
      <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"flex items-center justify-center w-56 h-56 border border-gray-200 rounded-lg bg-gray-50 dark:bg-gray-800 dark:border-gray-700"</span>&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"px-3 py-1 text-xs font-medium leading-none text-center text-blue-800 bg-blue-200 rounded-full animate-pulse dark:bg-blue-900 dark:text-blue-200"</span>&gt;</span>
            Uploading ...
          <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      );
<span class="hljs-comment">/** 
 Show relevant UI during the failed state. 
**/</span>
    <span class="hljs-keyword">case</span> <span class="hljs-string">"failed"</span>:
      <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-red-400 rounded-md py-6 px-3 text-slate-100 motion-safe:animate-bounce"</span>&gt;</span>
          An error occurred uploading your recording
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      );
<span class="hljs-comment">/** 
 Show relevant UI during the completed state. 
**/</span>
    <span class="hljs-keyword">case</span> <span class="hljs-string">"completed"</span>:
      <span class="hljs-keyword">return</span> (
        <span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">className</span>=<span class="hljs-string">"bg-green-400 rounded-md py-6 px-3 text-slate-100 motion-safe:animate-bounce"</span>&gt;</span>
          Successfully published your recording!
        <span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span></span>
      );
<span class="hljs-comment">/** 
 Typescript exhaustive checking
 @see https://www.typescriptlang.org/docs/handbook/2/narrowing.html#exhaustiveness-checking
**/</span>

    <span class="hljs-keyword">default</span>:
      <span class="hljs-keyword">const</span> _exhaustiveCheck: never = state;
      <span class="hljs-keyword">return</span> _exhaustiveCheck;
  }
};
</code></pre>
<p>Now, a user should be able to record in the browser, and we will go ahead and save the recording on our backend.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-19.15.22@2x.png" alt="Viewing saved recordings in the Firebase emulator." width="2428" height="1282" loading="lazy">
<em>Viewing saved recordings in the Firebase emulator.</em></p>
<h2 id="heading-how-to-fetch-data-from-the-server">How to Fetch Data from the Server</h2>
<p>We’re correctly saving user recordings, but at the moment they can’t be viewed on the homepage.</p>
<p>Let’s resolve that.</p>
<p>Our solution is to fetch the recordings on the server and send the rendered HTML page to the client.</p>
<p>Here’s the code solution:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/pages/index.astro</span>

---
<span class="hljs-keyword">import</span> { BUCKET_NAME } <span class="hljs-keyword">from</span> <span class="hljs-string">"@constants/firebase"</span>;
<span class="hljs-keyword">import</span> LinkCTA <span class="hljs-keyword">from</span> <span class="hljs-string">"@components/LinkCTA.astro"</span>;
<span class="hljs-keyword">import</span> AudioPlayer <span class="hljs-keyword">from</span> <span class="hljs-string">"@components/AudioPlayer.astro"</span>;
<span class="hljs-comment">// ...</span>

<span class="hljs-comment">// Represent the recordings with the "Audible" type alias</span>
type Audible = { <span class="hljs-attr">url</span>: string; timeCreated: string };

<span class="hljs-comment">// audibles will hold the list of "Audibles."</span>
<span class="hljs-keyword">let</span> audibles: Audible[] = [];
<span class="hljs-keyword">const</span> storage = getStorage(serverApp);


<span class="hljs-keyword">try</span> {
   <span class="hljs-comment">/**
     *  After verifying the user auth token 
       * and setting the token cookie ...
    */</span> 
    <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// get all recordings in the storage bucket</span>
    <span class="hljs-keyword">const</span> bucket = storage.bucket(BUCKET_NAME);
    <span class="hljs-keyword">const</span> [files] = <span class="hljs-keyword">await</span> bucket.getFiles();

    audibles = <span class="hljs-keyword">await</span> <span class="hljs-built_in">Promise</span>.all(
      files.map(<span class="hljs-keyword">async</span> (file) =&gt; {
        <span class="hljs-keyword">const</span> [metadata] = <span class="hljs-keyword">await</span> file.getMetadata();

        <span class="hljs-comment">// return the url and timeCreated metadata</span>
        <span class="hljs-keyword">return</span> {
          <span class="hljs-attr">url</span>: file.publicUrl(),
          <span class="hljs-attr">timeCreated</span>: metadata.timeCreated,
        };
      })
    );
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-built_in">console</span>.error(error);
    <span class="hljs-built_in">console</span>.error(<span class="hljs-string">"Error fetching audibles"</span>);
    <span class="hljs-keyword">return</span> Astro.redirect(<span class="hljs-string">"/signin"</span>);
  }
}

<span class="hljs-comment">//...</span>
---
</code></pre>
<p>Now update the component template section to render the “audibles”. We’ll leverage the <code>AudioPlayer</code> component, passing it the audible <code>url</code> and the <code>timeCreated</code> metadata.</p>
<pre><code class="lang-html"><span class="hljs-tag">&lt;<span class="hljs-name">div</span> <span class="hljs-attr">class</span>=<span class="hljs-string">"flex flex-col items-center"</span>&gt;</span>
    {
      audibles.length === 0 ? (
        <span class="hljs-tag">&lt;&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">Empty</span> /&gt;</span>
          <span class="hljs-tag">&lt;<span class="hljs-name">LinkCTA</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/record"</span>&gt;</span>Record<span class="hljs-tag">&lt;/<span class="hljs-name">LinkCTA</span>&gt;</span>
        <span class="hljs-tag">&lt;/&gt;</span>
      ) : (
        audibles
          .sort((a, b) =&gt;
            new Date(a.timeCreated) <span class="hljs-tag">&lt; <span class="hljs-attr">new</span> <span class="hljs-attr">Date</span>(<span class="hljs-attr">b.timeCreated</span>) ? <span class="hljs-attr">1</span> <span class="hljs-attr">:</span> <span class="hljs-attr">-1</span>
          )
          <span class="hljs-attr">.map</span>((<span class="hljs-attr">audible</span>) =&gt;</span> (
            <span class="hljs-tag">&lt;<span class="hljs-name">AudioPlayer</span> <span class="hljs-attr">url</span>=<span class="hljs-string">{audible.url}</span> <span class="hljs-attr">timeCreated</span>=<span class="hljs-string">{audible.timeCreated}</span> /&gt;</span>
          ))
      )
    }
<span class="hljs-tag">&lt;/<span class="hljs-name">div</span>&gt;</span>
</code></pre>
<p>In the code above, we display an <code>Empty</code> user interface empty if there are no audibles. Otherwise, we render a sorted list of audibles.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-19.06.31@2x.png" alt="Rendering the sorted list of audio recordings." width="2364" height="1631" loading="lazy">
<em>Rendering the sorted list of audio recordings.</em></p>
<h2 id="heading-how-to-submit-html-forms">How to Submit HTML forms</h2>
<p>The final puzzle in our application is handling the submission of the feedback form.</p>
<p>I’ve included this feature to show an example of handling a form within the same server-side rendered page, that is without creating an API endpoint to handle the form request.</p>
<p>Take a look at the form element and notice how its method attribute is set to <code>POST</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/layouts/BaseLayout.astro</span>
<span class="hljs-comment">// ... </span>
&lt;form <span class="hljs-class"><span class="hljs-keyword">class</span></span>=<span class="hljs-string">"mx-auto flex"</span> method=<span class="hljs-string">"POST"</span>&gt;
...
&lt;/form&gt;
</code></pre>
<p>By default, the browser will send a POST request to the server when this form is submitted, which we can capture and react upon.</p>
<p>In the frontmatter section of the <code>index.astro</code> page, we can add a condition to handle the feedback form requests as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ... </span>
<span class="hljs-keyword">if</span> (Astro.request.method === <span class="hljs-string">"POST"</span>) {
  <span class="hljs-keyword">try</span> {
    <span class="hljs-comment">// Get the form data </span>
    <span class="hljs-keyword">const</span> data = <span class="hljs-keyword">await</span> Astro.request.formData();
    <span class="hljs-comment">/**
    * Get the feedback value. 
    * Corresponds to the form input element value of the name, "feedback".
    */</span>
    <span class="hljs-keyword">const</span> feedback = data.get(<span class="hljs-string">"feedback"</span>);

    <span class="hljs-comment">// Do something with the data</span>
    <span class="hljs-built_in">console</span>.log({ feedback });

    <span class="hljs-comment">// Do something with the data</span>
  } <span class="hljs-keyword">catch</span> (error) {
    <span class="hljs-keyword">if</span> (error <span class="hljs-keyword">instanceof</span> <span class="hljs-built_in">Error</span>) {
      <span class="hljs-built_in">console</span>.error(error.message);
    }
  }
}
<span class="hljs-comment">// ...</span>
</code></pre>
<p>I’m keeping this simple by just logging the feedback on the server. But we could save this value to a database in the real world. The crux here is receiving the form values, as shown above.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-05-29-at-19.14.07@2x.png" alt="The logged feedback data. " width="1690" height="385" loading="lazy">
<em>The logged feedback data.</em></p>
<h2 id="heading-wrapping-up-this-chapter-6">Wrapping Up This Chapter</h2>
<p>Astro is great for building content-focused websites such as blogs, landing pages, and so on. But, we can do much more with it.</p>
<p>Suppose you can build the application as a multi-page application (MPA), that is not a single-page application, and can leverage islands of interactivity (component islands). In that case, you can build it with Astro.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-140.png" alt="Image" width="600" height="400" loading="lazy">
<em>Chapter eight.</em></p>
<h1 id="heading-chapter-8-build-your-own-astro-integrations-1">Chapter 8: Build Your Own  Astro Integrations</h1>
<p>At the end of this chapter, you’ll join the order of mages who wield great power to bend Astro to their will with new functionality and behaviour.</p>
<h2 id="heading-what-youll-learn-7">What You’ll Learn</h2>
<ul>
<li>The relationship between Astro and the Vite module bundler</li>
<li>The different types of integrations available in Astro</li>
<li>Build your first Astro integration</li>
<li>Understand the Astro hooks lifecycle</li>
<li>Deepen your knowledge of building custom Astro feature integrations</li>
</ul>
<h2 id="heading-astro-and-vite">Astro and Vite</h2>
<p>Before we dive into the beautiful world of Astro integrations, we need to know who’s powering the Astro build ship - and that’s <a target="_blank" href="https://vitejs.dev/">Vite</a>, the build tool all about speed, efficiency and flexibility. </p>
<p>Think of Vite as our trusty co-pilot, helping us bundle our web pages and creating a lightning-fast development environment.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/astro-vite-relationship.png" alt="The Astro Vite relationship." width="726" height="469" loading="lazy">
<em>The Astro Vite relationship.</em></p>
<p>To build the custom integrations we’re dreaming of, we may need to go beyond Astro and venture deep into Vite territory, for example customising the build step with Vite plugins.</p>
<p>Now, I know this might not be very clear, especially when we start talking about Vite in the upcoming sections of this chapter. But fear not - you now know why Vite is essential to the build process, and I’ll explain with examples in the coming sections of this chapter.</p>
<h2 id="heading-what-are-astro-integrations">What are Astro Integrations?</h2>
<p>By definition, Astro integrations extend Astro with new functionality and behaviour within your project.</p>
<p>We’ll find ourselves building three types of Astro integrations, namely:</p>
<ol>
<li><strong>Renderers</strong>: these integrations enable a framework component’s rendering (typically server-side rendering and client-side hydration). Examples of this include the official React, Preact, and Vue Astro integrations.</li>
<li><strong>Libraries</strong>: these integrations enable external library support within Astro. Examples of this include the official Tailwind and Partytown integrations.</li>
<li><strong>Features</strong>: these are integrations that extend the behaviour of Astro in a specific way, usually to support a user-defined feature set. Examples include the official <a target="_blank" href="https://docs.astro.build/en/guides/integrations-guide/sitemap/">sitemap</a> integration that generates a sitemap when you build your Astro project.</li>
</ol>
<p>For most people, the majority of integrations you build will be to support a particular feature, that is feature integrations. This will be the sole focus of this chapter. Once you have sufficient knowledge of building feature integrations, you can transfer the knowledge to library or renderer integrations.</p>
<p>Let’s get started with a contrived Astro integration.</p>
<h2 id="heading-hello-world-sorry-hello-integration">Hello World. Sorry – Hello, Integration</h2>
<p>Let’s get you acquainted with a basic hello world Astro integration. Even though we will be wielding swords and slaying dragons soon, before that you must get introduced to the tools of the trade.</p>
<h3 id="heading-project-objective">Project objective</h3>
<p>The goal for our first Astro integration is arguably straightforward: we will write a custom Astro integration that automatically logs a hello world message to the browser console on every application page.</p>
<p>Have you got it?</p>
<p>I heard a yes!</p>
<h3 id="heading-your-first-custom-integration">Your first custom integration</h3>
<p>We will approach this solution by injecting a script on every application page.</p>
<p>How?</p>
<p>Where?</p>
<p>When?</p>
<p>Hold your horses, mate!</p>
<p>Start by beginning a new Astro project with the familiar command:</p>
<pre><code class="lang-js">npm create astro@latest hello-astro-integration
</code></pre>
<p>Now that you’re a pro at this, name the project whatever you like, for example <code>hello-astro-integration</code>, and use a minimal (empty) template.</p>
<p>Open the application directory and head over to the <code>astro.config.mjs</code> file.</p>
<p>The <code>astro.config.mjs</code> file includes configuration options for our Astro project. This is where we define integrations for our project, that is this is where the magic happens.</p>
<p>At the moment, our <code>astro.config.mjs</code> file should be in the default empty state, as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 astro.config.mjs</span>
<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/config"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({});
</code></pre>
<p>Let’s change that by adding an empty <code>integrations</code> list to the configuration:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 astro.config.mjs</span>
<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/config"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">integrations</span>: [], <span class="hljs-comment">// 👀 look here </span>
});
</code></pre>
<p>In a nutshell, an Astro integration is represented by an object with <code>name</code> and <code>hooks</code> properties, as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 astro.config.mjs</span>
<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/config"</span>;

<span class="hljs-comment">// https://astro.build/config</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-comment">// 👀 look here </span>
  <span class="hljs-attr">integrations</span>: [
    {
      <span class="hljs-attr">name</span>: <span class="hljs-string">"astro-hello"</span>,
      <span class="hljs-attr">hooks</span>: {},
    },
  ],
});
</code></pre>
<p>In the code block above, we’ve outlined the object in the <code>integrations</code> array.</p>
<p>The name of the integration is <code>astro-hello</code>. We’ll discuss hooks in the coming section, but it represents extendable “hook” points within the Astro build lifecycle process.</p>
<p>For example, let’s leverage the first hook in the lifecycle process called <code>astro:config:setup</code>.</p>
<p>This hook is the starting point for the entire build lifecycle. It is triggered on initialisation before Astro has resolved the project configuration. It’s the perfect place to inject scripts onto a new page or extend the project configuration before it’s resolved.</p>
<p>Let’s take advantage of that by passing it into the hooks object and pointing it to a function invoked when the hook is triggered.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 astro.config.mjs</span>
<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/config"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">integrations</span>: [
    {
      <span class="hljs-attr">name</span>: <span class="hljs-string">"astro-hello"</span>,
      <span class="hljs-attr">hooks</span>: {
        <span class="hljs-comment">// 👀 hook: callbackFn</span>
        <span class="hljs-string">"astro:config:setup"</span>: <span class="hljs-function">(<span class="hljs-params">options</span>) =&gt;</span> {},
      },
    },
  ],
});
</code></pre>
<p>Note the <code>options</code> parameter in the hook callback. It is an object with the following type definition:</p>
<pre><code class="lang-js">{  
  <span class="hljs-attr">config</span>: AstroConfig;
  command: <span class="hljs-string">'dev'</span> | <span class="hljs-string">'build'</span>;
  isRestart: boolean;
  updateConfig: <span class="hljs-function">(<span class="hljs-params">newConfig: Record&lt;string, any&gt;</span>) =&gt;</span> <span class="hljs-keyword">void</span>;
  addRenderer: <span class="hljs-function">(<span class="hljs-params">renderer: AstroRenderer</span>) =&gt;</span> <span class="hljs-keyword">void</span>;
  addWatchFile: <span class="hljs-function">(<span class="hljs-params">path: URL | string</span>) =&gt;</span> <span class="hljs-keyword">void</span>;
  injectScript: <span class="hljs-function">(<span class="hljs-params">stage: InjectedScriptStage, content: string</span>) =&gt;</span> <span class="hljs-keyword">void</span>;
  injectRoute: <span class="hljs-function">(<span class="hljs-params">{ pattern: string, entryPoint: string }</span>) =&gt;</span> <span class="hljs-keyword">void</span>;
}
</code></pre>
<p>Luckily it contains the <code>injectScript</code> method we’re interested in:</p>
<pre><code class="lang-js">  injectScript: <span class="hljs-function">(<span class="hljs-params">stage: InjectedScriptStage, content: string</span>) =&gt;</span> <span class="hljs-keyword">void</span>;
</code></pre>
<p><code>stage</code> denotes how the script <code>content</code> should be injected into the page, and there are four possible values : <code>head-inline</code>, <code>before-hydration</code>, <code>page</code>, and <code>page-ssr</code>.</p>
<p>The <code>page</code> option will bundle and inject the script with other <code>&lt;script&gt;</code> tags defined in any Astro components on the page. The final output will eventually load this with a <code>&lt;script type="module&gt;</code>.</p>
<p>When I started tinkering with the integrations API, I tried silly things to get <code>injectScript</code> to work. I can confidently tell you these won’t work:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 👀 Error: Failed to parse source for import analysis</span>
<span class="hljs-comment">// because the content contains invalid JS syntax.</span>
injectScript(<span class="hljs-string">"page"</span>, <span class="hljs-string">"console.log('Hello World')"</span>)

<span class="hljs-keyword">const</span> log = <span class="hljs-function">() =&gt;</span> <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"me"</span>);
<span class="hljs-comment">// 👀 Uncaught ReferenceError: log is not defined</span>
options.injectScript(<span class="hljs-string">"page"</span>, <span class="hljs-string">"log()"</span>);
</code></pre>
<p>This saves you the futility I experienced until I looked in the Astro source code.</p>
<p>The <code>content</code> string parameter in <code>injectScript</code> refers to an import path. This is as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/config"</span>;

<span class="hljs-comment">// https://astro.build/config</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">integrations</span>: [
    {
      <span class="hljs-attr">name</span>: <span class="hljs-string">"astro-hello"</span>,
      <span class="hljs-attr">hooks</span>: {
        <span class="hljs-string">"astro:config:setup"</span>: <span class="hljs-function">(<span class="hljs-params">options</span>) =&gt;</span> {
          <span class="hljs-comment">//  👀 "page" option with an import path</span>
          options.injectScript(<span class="hljs-string">"page"</span>, <span class="hljs-string">`import '/src/scripts/
  globalLog.js'`</span>);
        },
      },
    },
  ],
});
</code></pre>
<p>Since we’re passing an import path to the script, let’s ensure the script exists.</p>
<p>Create a new script with the following content in <code>src/scripts/globalLog.js</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/scripts/globalLog.js</span>
<span class="hljs-keyword">const</span> logger = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> msg = <span class="hljs-string">"Hello Integrations"</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`%c <span class="hljs-subst">${msg}</span>`</span>, <span class="hljs-string">"background: black;  color: yellow"</span>);
};

logger();
</code></pre>
<p>The <code>logger</code> method calls the <code>console.log</code> method with a <code>Hello integrations</code> string while adding some colour to the message.</p>
<p>And voilà!</p>
<p>We have our first integration running as expected.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-06-at-05.29.53.png" alt="Working integration log printed in the browser console" width="874" height="578" loading="lazy">
<em>Working integration log printed in the browser console</em></p>
<p>We may create more pages, and the console message will be logged on every page in the application.</p>
<h3 id="heading-how-to-print-a-message-to-the-server-console">How to print a message to the server console</h3>
<p>Since we have hook points into the Astro build process, it is also possible to output logs to the server console.</p>
<p>This may be useful for usability or ascertaining that our custom integration works as expected.</p>
<p>At the moment, here’s the mess that my server logs look like:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-06-at-05.33.46.png" alt="The (messy) Astro server logs" width="675" height="309" loading="lazy">
<em>The (messy) Astro server logs</em></p>
<p>Yours should look familiar. This is from the incremental process of building our first integration.</p>
<p>Let’s go ahead and print something to the logs once we’ve successfully injected our script onto the page.</p>
<pre><code class="lang-js"><span class="hljs-comment">// ... </span>

<span class="hljs-attr">hooks</span>: {
    <span class="hljs-string">"astro:config:setup"</span>: <span class="hljs-function">(<span class="hljs-params">options</span>) =&gt;</span> {
      options.injectScript(<span class="hljs-string">"page"</span>, <span class="hljs-string">`import '/src/scripts/ 
    globalLog.js'`</span>);

     <span class="hljs-comment">// 👀 add a new log </span>
     <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"Injected hello integration script"</span>);
    },
},
</code></pre>
<p>Restart the server for a clean slate, and we should have the log printed as shown below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-06-at-05.38.59.png" alt="The server log from our hello world integration" width="669" height="354" loading="lazy">
<em>The server log from our hello world integration</em></p>
<p>Since we’re fancy developers who care about usability, let’s go ahead and make the log feel native to other Astro logs by adding some text formatting and colour via <code>kleur</code>.</p>
<p>Install the <code>kelur</code> package:</p>
<pre><code class="lang-js">npm install kleur
</code></pre>
<p>Once the installation is complete, we should now have a new log in the dev server that reads:</p>
<pre><code class="lang-js"><span class="hljs-number">05</span>:<span class="hljs-number">41</span>:<span class="hljs-number">02</span> AM [astro] update /package-lock.json
</code></pre>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-06-at-05.41.12.png" alt="Example native astro server log" width="629" height="345" loading="lazy">
<em>Example native astro server log</em></p>
<p><code>05:41:02</code> represents my current time.</p>
<p>Please do not ask me why I’m writing this chapter so early in the morning.</p>
<p>Let’s go ahead and make our log look similar. Instead of just using <code>console.log</code>, let’s introduce a <code>logServerMessage</code> that does our beautiful bidding as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 astro.config.mjs </span>

<span class="hljs-keyword">import</span> kleur <span class="hljs-keyword">from</span> <span class="hljs-string">"kleur"</span>;
<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/config"</span>;

<span class="hljs-comment">// 👀 The Intl.DateTimeFormat object enables language-sensitive </span>
<span class="hljs-comment">// date and time formatting.</span>
<span class="hljs-keyword">const</span> dateTimeFormat = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat([], {
  <span class="hljs-attr">hour</span>: <span class="hljs-string">"2-digit"</span>,
  <span class="hljs-attr">minute</span>: <span class="hljs-string">"2-digit"</span>,
  <span class="hljs-attr">second</span>: <span class="hljs-string">"2-digit"</span>,
});

<span class="hljs-keyword">const</span> logServerMessage = <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
  <span class="hljs-comment">// 👀 Get a new date string using the dateTimeFormat object</span>
  <span class="hljs-keyword">const</span> date = dateTimeFormat.format(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>());

  <span class="hljs-comment">// log to console with kleur colours and formatting</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${kleur.gray(date)}</span> <span class="hljs-subst">${kleur
    .bold()
    .cyan(<span class="hljs-string">"[astro-hello-integration]"</span>)}</span> <span class="hljs-subst">${message}</span>
  `</span>);
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-comment">// ... same content as before</span>
});
</code></pre>
<p>Now we should have a beautiful log message that feels native to Astro, like the other server console logs.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-06-at-05.47.14.png" alt="The custom integration &quot;native feeling&quot; server log" width="640" height="230" loading="lazy">
<em>The custom integration "native feeling" server log</em></p>
<h3 id="heading-custom-integrations-as-factory-functions">Custom integrations as factory functions</h3>
<p>Our current implementation is beginning to clog the Astro configuration file.</p>
<p>In practice, instead of inlining our custom Astro integration, it’s likely to live in a separate file as a factory function, that is a function that creates and returns the Astro integration object.</p>
<p>Let’s do that – it'll be something of a refactor.</p>
<p>Move the entire integration content into a new <code>src/integrations/astro-hello.ts</code> file.</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/integrations/astro-hello.ts</span>
<span class="hljs-keyword">import</span> kleur <span class="hljs-keyword">from</span> <span class="hljs-string">"kleur"</span>;

<span class="hljs-keyword">const</span> dateTimeFormat = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat([], {
  <span class="hljs-attr">hour</span>: <span class="hljs-string">"2-digit"</span>,
  <span class="hljs-attr">minute</span>: <span class="hljs-string">"2-digit"</span>,
  <span class="hljs-attr">second</span>: <span class="hljs-string">"2-digit"</span>,
});

<span class="hljs-keyword">const</span> logServerMessage = <span class="hljs-function">(<span class="hljs-params">message</span>) =&gt;</span> {
  <span class="hljs-keyword">const</span> date = dateTimeFormat.format(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>());
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${kleur.gray(date)}</span> <span class="hljs-subst">${kleur
    .bold()
    .cyan(<span class="hljs-string">"[astro-hello-integration]"</span>)}</span> <span class="hljs-subst">${message}</span>
    `</span>);
};

<span class="hljs-comment">// 👀 Introduce a default export function that returns the Astro </span>
<span class="hljs-comment">// integration object.</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">helloIntegration</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"astro-hello"</span>,
    <span class="hljs-attr">hooks</span>: {
      <span class="hljs-string">"astro:config:setup"</span>: <span class="hljs-function">(<span class="hljs-params">options</span>) =&gt;</span> {
        options.injectScript(<span class="hljs-string">"page"</span>, <span class="hljs-string">`import '/src/scripts/
    globalLog.js'`</span>);

        logServerMessage(<span class="hljs-string">"Injected script"</span>);
      },
    },
  };
}
</code></pre>
<p>Now, add in TypeScript types:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/integrations/astro-hello.ts</span>

<span class="hljs-keyword">import</span> type { AstroIntegration } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;

<span class="hljs-keyword">const</span> logServerMessage = <span class="hljs-function">(<span class="hljs-params">message: string</span>) =&gt;</span> {
  <span class="hljs-comment">// ...</span>
};

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">helloIntegration</span>(<span class="hljs-params"></span>): <span class="hljs-title">AstroIntegration</span> </span>{
  <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>Oh yeah!</p>
<p>Our implementation is coming around nicely.</p>
<p>Now, let’s clean up <code>astro.config.mjs</code> by importing our integration as shown below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 astro.config.mjs</span>
<span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/config"</span>;
<span class="hljs-keyword">import</span> astroHello <span class="hljs-keyword">from</span> <span class="hljs-string">"./src/integrations/astro-hello"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-comment">// 👀 invoke the imported astroHello function in the list</span>
  <span class="hljs-attr">integrations</span>: [astroHello()],
});
</code></pre>
<p>And there we have it! A sparkly clean, custom Astro integration.</p>
<p>You may view the complete source code on <a target="_blank" href="https://github.com/understanding-astro/hello-astro-integration">GitHub</a>.</p>
<h2 id="heading-the-astro-hooks-lifecycle">The Astro Hooks Lifecycle</h2>
<p>By definition, lifecycle refers to the series of changes in the life of an organism. For example, a butterfly starts as an egg, larva, pupa, and then becomes a full-blown adult.</p>
<p>Until human cloning becomes available, there’s a decent chance you also started as an infant, then grew into a toddler, eventually puberty, and then found your way into adulthood. At least, I hope so!</p>
<p>In software, the term lifecycle represents a process’s different stages.</p>
<p>With Astro hooks, we explicitly refer to the stages Astro goes through while building your application pages. This is the process from resolving the Astro configuration setup to spinning up a local server to bundling your pages statically or server-side rendered in production.</p>
<p>The entire process is what I call the Astro hooks lifecycle.</p>
<p>To get productive in developing custom integrations, we’ll need to know where in the lifecycle we need to effect a change or react to.</p>
<p>Hooks are functions which are called at various stages of the build. To interact with the build process, we'll leverage the following ten hooks:</p>
<ul>
<li><code>astro:config:setup</code></li>
<li><code>astro:config:done</code></li>
<li><code>astro:server:setup</code></li>
<li><code>astro:server:start</code></li>
<li><code>astro:server:done</code></li>
<li><code>astro:build:start</code></li>
<li><code>astro:build:setup</code></li>
<li><code>astro:build:generated</code></li>
<li><code>astro:build:ssr</code></li>
<li><code>astro:build:done</code></li>
</ul>
<p>Ten seems like a lot to remember. Good thing it isn’t a dozen hooks (twelve). And you don’t have to memorise these. Instead, understand how they work. You can always refer to the official reference when needed.</p>
<h3 id="heading-the-when-and-why-of-hooks">The when and why of hooks</h3>
<p>One of the first questions I asked myself when I started tinkering with Astro integrations was when exactly are these triggered, and is there some order of execution to them?</p>
<p>Well, the answer to these lies below, but first, consider the following diagram that depicts the order in which the hooks are executed:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/hooks-lifecycle.png" alt="Execution order of Astro hooks " width="1939" height="3088" loading="lazy">
<em>Execution order of Astro hooks</em></p>
<p>Kicking off the process are two hooks:</p>
<ol>
<li><code>astro:config:setup</code></li>
<li><code>astro:config:done</code></li>
</ol>
<p>These hooks are always executed regardless of the Astro build process.</p>
<p>Here’s a breakdown of when these are executed and how we could leverage these in our custom integrations:  </p>
<table>
    <thead>
        <tr>
            <th>
                Hook
            </th>
            <th>
                Executed when … 
            </th>
            <th>
                 Why use this … 
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <br><br><code>astro:config:<br>setup</code><br>
            </td>
            <td>
                <br><br>Astro is initialised. <br><br>This happens <br>before the Astro project configuration (or Vite config) <br>are resolved. 
            </td>
            <td>
                <br><br>Consider being the first one at the pub before it opens. You can cause a ruckus before anyone else even shows up! <br><br>Similarly, this is where you swoop in to extend the project configuration e.g., updating the Astro config, applying Vite plugins, adding component renderers and injecting scripts before Astro knows what hit it. 
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>astro:config:done</code>
            </td>
            <td>
                <br><br>The Astro config has been resolved. At this point, every <code>astro:config:setup</code> hook has been invoked for every integration in the project. <br><br><br>
            </td>
            <td>
                <br><br>Like a perfect pint of beer, we patiently wait to grab the glass only after it’s been poured. <br><br>Similarly, after the Astro config has finally got its act together and all the other integrations have done their thing, this is where we retrieve the final config for use in our integration. <br>
            </td>
        </tr>
    </tbody>
</table>

<p>Once <code>astro:config:done</code> is fired, there are two branches to consider: development and production mode.</p>
<p>When developing your apps locally, without initiating a production build typically via <code>npm run build</code> or <code>astro build</code>, the left side of the chart depicts the order of hooks execution in developer mode. Then the following hooks are invoked:</p>
<ol>
<li><code>astro:server:setup</code></li>
<li><code>astro:server:start</code></li>
<li><code>astro:server:done</code></li>
</ol>
<p>These hooks are executed when building your app for local development.</p>
<p>Here’s a breakdown of when these are executed and how we could leverage these in our custom integrations:  </p>
<table>
    <thead>
        <tr>
            <th>
                Hook
            </th>
            <th>
                Executed when … 
            </th>
            <th>
                 Why use this … 
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <br><br><code>astro:server:<br>setup</code><br>
            </td>
            <td>
                <br><br>The Vite server has just been created in development mode.<br><br>This is before the <code>listen()</code>server event is fired i.e., before starting the server.
            </td>
            <td>
                <br><br>This is where we may update the Vite server options and middleware.<br><br>The Vite dev server object is passed as an argument to our hook.
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>astro:server:start</code>
            </td>
            <td>
                <br><br>The Vite <code>listen()</code>method has just been fired i.e., the server is running. <br><br><br>
            </td>
            <td>
                <br><br>Like tech-savvy superheroes, we can jump in here to save the day at the last minute - well, if that involves intercepting network requests. <br><br>This is where we may jump in to intercept network requests at the specified dev server address (passed as an argument to our hook)
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>astro:server:done</code>
            </td>
            <td>
                <br><br>The dev server has just been closed.
            </td>
            <td>
                <br><br>Like cleaners coming in after the party to sweep up the mess, this is where we run cleanups. <br><br>If you wish to clean up any side effects triggered during <code>astro:server:setup</code> or <code>astro:server:start</code>, here’s where you do so!
            </td>
        </tr>
    </tbody>
</table>

<p>When we run a production build, two hooks will always be triggered. These are</p>
<ol>
<li><code>astro:build:start</code></li>
<li><code>astro:build:setup</code></li>
</ol>
<p>And here’s a breakdown of when these are executed and how we could leverage these in our custom integrations:</p>
<table>
    <thead>
        <tr>
            <th>
                Hook
            </th>
            <th>
                Executed when … 
            </th>
            <th>
                 Why use this … 
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <br><br><code>astro:build:<br>start</code><br>
            </td>
            <td>
                <br><br>The Astro config is completely resolved but before the production build begins. 
            </td>
            <td>
                <br><br>The production build is about to start but perhaps you want to set up some global objects or clients needed during the build? <br>Here’s where we do so.
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>astro:build:setup</code>
            </td>
            <td>
                <br><br>The build is just about to get started. At this point, the build config is fully constructed. <br><br><br>
            </td>
            <td>
                <br><br>To steal the perfect phrase from the official Astro documentation: this is our final chance to modify the build. <br><br>It's like getting ready for a night out - we’ve put on our best outfit and look sharp, but we just need to add that one last accessory to complete the look. This is our chance to do just that - to overwrite some defaults and make sure everything is looking top-notch. <br><br>I must mention that if you're not sure whether to use this hook or <code>astro:build:start</code>, go for <code>astro:build:start</code> instead.
            </td>
        </tr>
    </tbody>
</table>

<p>Now, depending on whether the page being built is statically generated or to be server-side rendered, either <code>astro:build:generated</code> or <code>astro:build:ssr</code> will be invoked, and finally, <code>astro:build:done</code>.</p>
<p>Yes, you guessed it. Here’s the final breakdown of when these are executed and how we could leverage these in our custom integrations:</p>
<table>
    <thead>
        <tr>
            <th>
                Hook
            </th>
            <th>
                Executed when … 
            </th>
            <th>
                 Why use this … 
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <br><br><code>astro:build:<br>generated</code><br>
            </td>
            <td>
                <br><br>The static production build has completely generated routes and assets. 
            </td>
            <td>
                <br><br>Access generated routes and assets before build artefacts are cleaned up. As per the official docs, this is an uncommon case and we might be better off using <code>astro:build:done</code> in many cases., except we really need to access these files before cleanup.
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>astro:build:ssr</code>
            </td>
            <td>
                <br><br>A production SSR build is completed.<br><br><br>
            </td>
            <td>
                <br><br>To get access to the SSR manifest. This is helpful when creating custom SSR builds.
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>astro:build:done</code>
            </td>
            <td>
                <br><br>The production build is complete!
            </td>
            <td>
                <br><br>This is where we may access the generated routes and assets e.g., to be copied somewhere. For transforming generated assets, consider using a Vite plugin and configuring <code>astro:config:setup</code>.
            </td>
        </tr>
    </tbody>
</table>

<h3 id="heading-examining-the-hooks-evaluation-order">Examining the hooks evaluation order</h3>
<p>Even though we’ve taken time to explore when the Astro hooks are invoked, there’s no better teacher than practice.</p>
<p>Let’s go ahead and write out a simple integration that spits out a log to the server console when invoked. Then, you can tinker with building several pages for production and inspect the logs.</p>
<p>Our eventual goal is to have a custom integration that looks something like this:</p>
<pre><code class="lang-js">{
  <span class="hljs-attr">name</span>: <span class="hljs-string">"some-identifier"</span>,
  <span class="hljs-attr">hooks</span>: {
   <span class="hljs-string">"hook-name"</span>: <span class="hljs-function">() =&gt;</span> {
     <span class="hljs-comment">// log hook name so we know it's been invoked</span>
   }
  }
}
</code></pre>
<p>Makes sense?</p>
<p>Let’s go ahead and build this out.</p>
<p>If building along, extend the hello world application or create a new Astro application with the following custom integration:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 src/integrations/lifecycle-logs.ts</span>

<span class="hljs-keyword">import</span> kleur <span class="hljs-keyword">from</span> <span class="hljs-string">"kleur"</span>;
<span class="hljs-keyword">import</span> type { AstroIntegration } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;

<span class="hljs-comment">//Create a new dateTimeFormat object</span>
<span class="hljs-keyword">const</span> dateTimeFormat = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat([], {
  <span class="hljs-attr">hour</span>: <span class="hljs-string">"2-digit"</span>,
  <span class="hljs-attr">minute</span>: <span class="hljs-string">"2-digit"</span>,
  <span class="hljs-attr">second</span>: <span class="hljs-string">"2-digit"</span>,
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> lifecycleLogs = <span class="hljs-function">() =&gt;</span> {
  <span class="hljs-keyword">const</span> hooks = [
    <span class="hljs-string">`astro:config:setup`</span>,
    <span class="hljs-string">`astro:config:done`</span>,
    <span class="hljs-string">`astro:server:setup`</span>,
    <span class="hljs-string">`astro:server:start`</span>,
    <span class="hljs-string">`astro:server:done`</span>,
    <span class="hljs-string">`astro:build:start`</span>,
    <span class="hljs-string">`astro:build:setup`</span>,
    <span class="hljs-string">`astro:build:generated`</span>,
    <span class="hljs-string">`astro:build:ssr`</span>,
    <span class="hljs-string">`astro:build:done`</span>,
  ] <span class="hljs-keyword">as</span> <span class="hljs-keyword">const</span>;

  <span class="hljs-comment">// base integration structure. "hooks" will be updated</span>
  <span class="hljs-keyword">let</span> integration: AstroIntegration = {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"astro-lifecycle-logs"</span>,
    <span class="hljs-attr">hooks</span>: {},
  };

  <span class="hljs-comment">// loop over the hooks list and add the name and log</span>
  <span class="hljs-keyword">for</span> (<span class="hljs-keyword">const</span> hook <span class="hljs-keyword">of</span> hooks) {
    integration.hooks[hook] = <span class="hljs-function">() =&gt;</span> {
      <span class="hljs-comment">// 👀 Get a new date string</span>
      <span class="hljs-keyword">const</span> date = dateTimeFormat.format(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>());

      <span class="hljs-comment">// log with kleur colours and formatting</span>
      <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${kleur.gray(date)}</span> <span class="hljs-subst">${kleur
        .bold()
        .yellow(<span class="hljs-string">"[lifecycle-log]"</span>)}</span> <span class="hljs-subst">${kleur.green(hook)}</span>
        `</span>);
    };
  }

  <span class="hljs-keyword">return</span> integration;
};


<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> lifecycleLogs;
</code></pre>
<p>Import <code>lifecycleLogs</code> and add it to your project’s integration list, then (re)start your application to see the logs in the console as shown below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-08-at-17.13.02.png" alt="The dev lifecycle hooks " width="509" height="297" loading="lazy">
<em>The dev lifecycle hooks</em></p>
<p>As an exercise, I suggest you add a new SSR page and run a production build to see the order of hooks execution logged.</p>
<p>Here’s an example with two pages:</p>
<ul>
<li>a static <code>index.astro</code> page</li>
<li>a server-side rendered <code>ssr.astro</code> page</li>
</ul>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-08-at-18.16.15.png" alt="The entire hook lifecycle logged " width="693" height="628" loading="lazy">
<em>The entire hook lifecycle logged</em></p>
<h2 id="heading-how-to-build-a-default-pre-render-integration">How to Build a Default Pre-render Integration</h2>
<p>When we enable SSR in our project, we can also opt-in to pre-rendering, that is to statically render some files at build time.</p>
<p>The way to do this is to add an <code>export const prerender = true</code> to the desired static page(s).</p>
<p>There was a time Astro didn’t support hybrid rendering, so this is an excellent feature.</p>
<p>But in practice, we may have multiple static pages and just a few server-side rendered ones. Adding <code>export const prerender = true</code> to all the static pages gets painfully annoying.</p>
<p>The other day I started building an Astro application that was predominantly statically rendered. Then I realised I needed one server-side rendered route. </p>
<p>At this point, I change my <code>astro.config.mjs</code> file to include <code>output: server</code>. Consequently, I had to go to all the existing static pages to add <code>export const prerender = true</code>. This wasn’t pleasant.</p>
<p>You may view the complete source code on <a target="_blank" href="https://github.com/understanding-astro/astro-integration-prerender-by-default">GitHub</a>.</p>
<h3 id="heading-project-objective-1">Project objective</h3>
<p>The goal of our custom integration is to flip the default hybrid rendering behaviour of Astro.</p>
<p>By default, with an <code>output: server</code> in our configuration, all pages are assumed to be server-rendered, and we must explicitly add <code>export const prerender = true</code> to our static pages.</p>
<p>We want to achieve a different behaviour for cases when we have more static pages, that is:</p>
<ul>
<li>By default, with <code>output: server</code> in our configuration, render all pages statically at build time – prerender by default.</li>
<li>Add <code>export const prerender = false</code> to render a page server-side explicitly.</li>
</ul>
<p>See what we’ve done there?</p>
<p>Now, please give it a think. How do we achieve this?</p>
<p>At the time of writing, there’s a public roadmap for Astro to <a target="_blank" href="https://github.com/withastro/roadmap/issues/539">support default pre-rendering</a> internally. Until then, let’s bend Astro to our will.</p>
<h3 id="heading-integration-api">Integration API</h3>
<p>We will design our integration as a factory function named <code>prerenderByDefault</code>.</p>
<p>Our users will go ahead and invoke this function within their <code>integrations</code> list, as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">integrations</span>: [prerenderByDefault()],
});
</code></pre>
<p>By default, we will log messages to the server console but expose a <code>silent</code> parameter to prevent server console logs.</p>
<p>Astro integrations usually support configurations by passing arguments to the factory function. Below’s our proposed API:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">integrations</span>: [prerenderByDefault({
     <span class="hljs-attr">silent</span>: <span class="hljs-literal">true</span> <span class="hljs-comment">// or false (boolean)</span>
  })],
});
</code></pre>
<p>Finally, we will add some basic validation within our integration. If the user doesn’t have an <code>output: server</code> or <code>adapter</code> option in their configuration, we will skip pre-rendering by default. This is because we only want our integration to take effect during hybrid rendering, which is only activated with <code>output: server</code> in the user’s project configuration.</p>
<h3 id="heading-technical-solution-overview">Technical solution overview</h3>
<p>At its core, our integration will take advantage of two lifecycle hooks: <code>astro:config:setup</code> and <code>astro:config:done</code> as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">prerenderByDefault</span>(<span class="hljs-params"></span>) </span>{
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"astro-prerender-by-default"</span>,
    <span class="hljs-attr">hooks</span>: {
      <span class="hljs-string">"astro:config:setup"</span>() {

      },
      <span class="hljs-string">"astro:config:done"</span>(options) {

      },
    },
  };
}
</code></pre>
<p>In <code>astro:config:done</code>, we will retrieve the project’s resolved configuration and perform our validation.</p>
<pre><code class="lang-js"><span class="hljs-string">"astro:config:done"</span>(options) {

   <span class="hljs-comment">// 1. Get resolved config from options.config </span>
   <span class="hljs-comment">// 2. Validate that the config object has the right </span>
    <span class="hljs-comment">//   output and adapter values </span>

}
</code></pre>
<p>In <code>astro:config:setup</code>, we will swoop in and extend the user’s Astro project configuration by applying a custom Vite plugin.</p>
<pre><code class="lang-js"><span class="hljs-string">"astro:config:setup"</span>(options) {
    <span class="hljs-comment">// Apply a custom Vite plugin here</span>
}
</code></pre>
<p>When Astro builds our project, it does so using Vite. Integrations are to Astro what plugins are to Vite. To extend Vite, we use plugins.</p>
<p>We can tap into the Vite build lifecycle to access the user’s Astro code (particularly their <code>pages</code>) during the build process.</p>
<p>Now, here comes the fun part.</p>
<p>First, we will parse the Astro code into Abstract Syntax Trees (ASTs).</p>
<p>Essentially, an AST serves as a means of representing the code’s structure in a programming language. Just as a sentence can be broken down into nouns, verbs, and adjectives, an AST dissects code into its essential components – variables, functions, and operations – and reflects their relationships in a tree-like structure.</p>
<p>A valid Astro component may take different forms. But the <code>frontmatter</code> must always be the first child node of the root node.</p>
<p>For example, the following is correct:</p>
<pre><code class="lang-js">--- 
 <span class="hljs-comment">// frontmatter</span>
---
<span class="hljs-comment">// markup goes here </span>
<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span> Hello world <span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span></span>
</code></pre>
<p>The following is invalid:</p>
<pre><code class="lang-js">&lt;h1&gt; Hello world &lt;/h1&gt;

--- 
 <span class="hljs-comment">// frontmatter </span>
---
</code></pre>
<p>With this heuristic, we will grab the first child node in the root of our parsed AST and make some decisions:</p>
<ul>
<li>If the file already has a <code>prerender</code> export, do nothing, that is leave the file as is.</li>
<li>Otherwise, update the code to include <code>export const prerender = true</code> – so we will update the code within our integration. It’s important to note that this only transforms the page’s code to be built. It does not update the local file.</li>
<li>Finally, if a page has no frontmatter, we will create one and include the <code>export const prerender = true</code> code snippet.</li>
</ul>
<h3 id="heading-how-to-initialise-projects-via-cli-flags">How to Initialise projects via CLI flags</h3>
<p>The <code>create astro</code> command is robust. But sometimes you don’t have the patience to select every option via prompts.</p>
<p>In such cases, use the CLI flags as shown below.</p>
<p>Initialise a new project with the following command:</p>
<pre><code class="lang-bash">npm create astro@latest -- --template=minimal    
--typescript=strictest --git --install   
astro-integration-prerender-by-default
</code></pre>
<p>This will set up a new Astro project in the <code>prerenderbyDefault</code>directory with CLI flags passed instead of via prompts, that is <code>--template=minimal</code> will use the minimal template, <code>--template=strictest</code> will use the <code>strictest</code> typescript config, <code>--git</code> will initialise a Git repo and <code>--install</code> will install the dependencies.</p>
<p>Here’s a quick table of the available CLI flags:</p>
<table>
    <thead>
        <tr>
            <th>
                Name
            </th>
            <th>
                Description
            </th>
        </tr>
    </thead>
    <tbody>
        <tr>
            <td>
                <code>--template &lt;name&gt;</code>
            </td>
            <td>
                Specify the template. Where <code>name</code> could be <br>any of the directories in <br><a href="https://github.com/withastro/astro/tree/main/examples/">https://github.com/withastro/astro/tree/main/examples/</a>.
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>--install</code> / <code>--no-install</code>
            </td>
            <td>
                <br><br>Install dependencies (or not).
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>--git</code> / <code>--no-git</code>
            </td>
            <td>
                <br><br>Initialize git repo (or not).
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>--yes</code> (<code>-y</code>)
            </td>
            <td>
                <br><br>Skip all prompts and accept the defaults.
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>--no</code> (<code>-n</code>) 
            </td>
            <td>
                <br><br>Skip all prompts and decline the defaults.
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>--dry-run</code>
            </td>
            <td>
                <br><br>Walk through the project creation steps <br>without any actual execution. Useful for a “dry run” 
            </td>
        </tr>
        <tr>
            <td>
                <br><br><code>--skip-houston</code>
            </td>
            <td>
                <br><br>Skip the Houston animation. If in a hurry, this saves some time and starts the prompt directly. 
            </td>
        </tr>
        <tr>
            <td>
                <br><br> <code>--typescript &lt;option&gt;</code>
            </td>
            <td>
                <br><br>Where <code>option</code> is <code>strict</code> , <code>strictest</code> or<code>relaxed</code>
            </td>
        </tr>
    </tbody>
</table>

<p>Now, change the directory and run the new Astro application:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">cd</span> ./astro-integration-prerender-by-default &amp;&amp; npm run start
</code></pre>
<p>By default, this should start the application on an available port, for example <code>localhost:3000</code>.</p>
<h3 id="heading-how-to-set-up-the-integration">How to set up the integration</h3>
<p>Create a new <code>index</code> file in <code>integrations/prerenderByDefault</code> and create the integration factory function as shown below:</p>
<pre><code class="lang-bash"><span class="hljs-built_in">export</span> default <span class="hljs-keyword">function</span> <span class="hljs-function"><span class="hljs-title">prerenderByDefault</span></span>() {
  <span class="hljs-built_in">return</span> {
    name: <span class="hljs-string">"astro-prerender-by-default"</span>,
    hooks: {
      <span class="hljs-string">"astro:config:setup"</span>() {},
      <span class="hljs-string">"astro:config:done"</span>() {},
    },
  };
}
</code></pre>
<p>Let’s add support for configuring the integration by accepting a configuration object.</p>
<p>Go ahead and create a <code>types.ts</code> file in <code>integrations/prerenderByDefault</code> as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> type Config =
  | {
      silent?: boolean;
    }
  | <span class="hljs-literal">undefined</span>;
</code></pre>
<p>Now, let’s add a <code>config</code> parameter to the <code>prerenderByDefault</code> factory function and type its return value as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> type { AstroIntegration } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;
<span class="hljs-keyword">import</span> type { Config } <span class="hljs-keyword">from</span> <span class="hljs-string">"./types"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">prerenderByDefault</span>(<span class="hljs-params">config: Config</span>): <span class="hljs-title">AstroIntegration</span> </span>{
    <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>Now go ahead and add the integration in the project’s config file:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { defineConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro/config"</span>;
<span class="hljs-keyword">import</span> prerenderByDefault <span class="hljs-keyword">from</span> <span class="hljs-string">"./integrations/prerenderByDefault"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">integrations</span>: [prerenderByDefault()],
});
</code></pre>
<h3 id="heading-how-to-validate-a-resolved-astro-configuration">How to validate a resolved Astro configuration</h3>
<p>Let’s go ahead to handle our integration validation. First, we will create an <code>isValidAstroConfig</code> method to receive an Astro configuration and a validation result.</p>
<p>Here’s the implementation below:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 prerenderByDefault/isValidAstroConfig.ts</span>

<span class="hljs-keyword">import</span> type { AstroConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"astro"</span>;

<span class="hljs-comment">/**
 * @param config: the fully resolved astro project config
 * @returns validation result
 */</span>
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> isValidAstroConfig = <span class="hljs-function">(<span class="hljs-params">config: AstroConfig</span>) =&gt;</span> {
  <span class="hljs-keyword">if</span> (config.output !== <span class="hljs-string">"server"</span>) {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">type</span>: <span class="hljs-string">"invalid_output_config"</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">false</span> } <span class="hljs-keyword">as</span> <span class="hljs-keyword">const</span>;
  }

  <span class="hljs-keyword">if</span> (!config.adapter) {
    <span class="hljs-keyword">return</span> { <span class="hljs-attr">type</span>: <span class="hljs-string">"invalid_adapter_config"</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">false</span> } <span class="hljs-keyword">as</span> <span class="hljs-keyword">const</span>;
  }

  <span class="hljs-comment">/**
   * configuration is valid
   */</span>
  <span class="hljs-keyword">return</span> { <span class="hljs-attr">type</span>: <span class="hljs-string">"success"</span>, <span class="hljs-attr">value</span>: <span class="hljs-literal">true</span> } <span class="hljs-keyword">as</span> <span class="hljs-keyword">const</span>;
};
</code></pre>
<p>I’ve decided to return an object instead of simple boolean values to utilise typescript’s <a target="_blank" href="https://www.typescriptlang.org/docs/handbook/2/narrowing.html#exhaustiveness-checking">exhaustiveness checking</a>.</p>
<p>Now, let’s leverage <code>isValidAstroConfig</code> in the <code>astro:config:done</code> hook by doing the following:</p>
<ul>
<li>Retrieve the final Astro project configuration</li>
<li>Validate the configuration</li>
<li>Log messages to the server console based on the validation result</li>
</ul>
<p>Here’s how:</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> <span class="hljs-function"><span class="hljs-keyword">function</span> <span class="hljs-title">prerenderByDefault</span>(<span class="hljs-params">config: Config</span>): <span class="hljs-title">AstroIntegration</span> </span>{
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"astro-prerender-by-default"</span>,
    <span class="hljs-attr">hooks</span>: {
      <span class="hljs-string">"astro:config:setup"</span>() {},
      <span class="hljs-comment">// 👀 look below </span>
      <span class="hljs-string">"astro:config:done"</span>(options) {
        <span class="hljs-comment">// get the 'silent' integration config property, default to false.</span>
        <span class="hljs-keyword">const</span> silent = config?.silent ?? <span class="hljs-literal">false</span>;

        <span class="hljs-comment">// validate the resolved project configuration</span>
        <span class="hljs-keyword">const</span> validationResult = isValidAstroConfig(options.config);

        <span class="hljs-comment">/**
         * Leverage Typescript exhaustive check to handle all
         * validation types and log messages where appropriate
         */</span>
        <span class="hljs-keyword">switch</span> (validationResult.type) {
          <span class="hljs-keyword">case</span> <span class="hljs-string">"invalid_adapter_config"</span>:
            log({
              silent,
              <span class="hljs-attr">message</span>: <span class="hljs-string">`Adapter not set for hybrid rendering. Skipping`</span>,
            });
            <span class="hljs-keyword">return</span>;

          <span class="hljs-keyword">case</span> <span class="hljs-string">"invalid_output_config"</span>:
            log({
              silent,
              <span class="hljs-attr">message</span>: <span class="hljs-string">`Config output not set to "server". Skipping`</span>,
            });
            <span class="hljs-keyword">return</span>;

          <span class="hljs-keyword">case</span> <span class="hljs-string">"success"</span>:
            <span class="hljs-keyword">return</span>;

          <span class="hljs-keyword">default</span>:
            <span class="hljs-keyword">const</span> _exhaustiveCheck: never = validationResult;
            <span class="hljs-keyword">return</span> _exhaustiveCheck;
        }
      },
    },
  };
}
</code></pre>
<p>We’re calling a <code>log</code> function to write messages to the server console depending on the validation result, but this function does not exist.</p>
<p>We’ve written similar log functions, so here’s the code for this one:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 prerenderByDefault/log.ts</span>

<span class="hljs-keyword">import</span> kleur <span class="hljs-keyword">from</span> <span class="hljs-string">"kleur"</span>;

type LogOptions = {
  <span class="hljs-attr">silent</span>: boolean;
  message: string;
};

<span class="hljs-keyword">const</span> dateTimeFormat = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Intl</span>.DateTimeFormat([], {
  <span class="hljs-attr">hour</span>: <span class="hljs-string">"2-digit"</span>,
  <span class="hljs-attr">minute</span>: <span class="hljs-string">"2-digit"</span>,
  <span class="hljs-attr">second</span>: <span class="hljs-string">"2-digit"</span>,
});

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> log = <span class="hljs-function">(<span class="hljs-params">options: LogOptions</span>) =&gt;</span> {
  <span class="hljs-comment">// do not log if the "silent" argument is passed</span>
  <span class="hljs-keyword">if</span> (options.silent) {
    <span class="hljs-keyword">return</span>;
  }

  <span class="hljs-comment">// get new date</span>
  <span class="hljs-keyword">const</span> date = dateTimeFormat.format(<span class="hljs-keyword">new</span> <span class="hljs-built_in">Date</span>());

  <span class="hljs-comment">// log to the console with colours and text formatting</span>
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">`<span class="hljs-subst">${kleur.gray(date)}</span> <span class="hljs-subst">${kleur
    .bold()
    .magenta(<span class="hljs-string">"[astro-prerender-by-default]"</span>)}</span> <span class="hljs-subst">${options.message}</span>
  `</span>);
};
</code></pre>
<p>Now make sure to import the <code>log</code> function in <code>prerenderByDefault/index.ts</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { log } <span class="hljs-keyword">from</span> <span class="hljs-string">"./log"</span>;
...
</code></pre>
<p>Now if we go ahead and build the project with <code>npm run build</code>, we should have our integration validation log displayed as shown below:</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-12-at-07.01.41.png" alt="Validation server log " width="706" height="333" loading="lazy">
<em>Validation server log</em></p>
<p>This is expected because the project does not have a <code>server</code> output configured. In this case, hybrid rendering cannot be utilised.</p>
<h3 id="heading-how-to-apply-vite-plugins-in-custom-integrations">How to apply Vite plugins in custom integrations</h3>
<p>Astro uses Vite under the hood. As such, it’s possible to pass additional configurations to Vite in the <code>astro.config.mjs</code> file, for example:</p>
<pre><code class="lang-js">{
  <span class="hljs-attr">vite</span>: {
    <span class="hljs-comment">//This adds a custom plugin directly to the Astro config</span>
    <span class="hljs-attr">plugins</span>: [myPlugin()]
  }
}
</code></pre>
<p>Consequently, we can take advantage of this in our integration.</p>
<p>Remember from the lifecycle hooks section that <code>astro:config:setup</code> is where we may swoop in to extend the project configuration. Let’s do so now:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> { injectVitePlugin } <span class="hljs-keyword">from</span> <span class="hljs-string">"./injectVitePlugin"</span>;
<span class="hljs-comment">// ...</span>

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"astro-prerender-by-default"</span>,
    <span class="hljs-attr">hooks</span>: {
      <span class="hljs-comment">// 👀 look here</span>
      <span class="hljs-string">"astro:config:setup"</span>(options) {
        options.updateConfig({
          <span class="hljs-attr">vite</span>: {
            <span class="hljs-attr">plugins</span>: [injectVitePlugin()],
          },
        });
      },
}
<span class="hljs-comment">// ...</span>
</code></pre>
<p>In the plugins array, we’re invoking <code>injectVitePlugin()</code>, which should return a valid Vite plugin.</p>
<p>Oh, but what’s a valid Vite plugin, you might ask?</p>
<p>Similar to Astro integrations, a Vite plugin is represented by an object with a name property and specific hooks, which are methods on the object, for example:</p>
<pre><code class="lang-js">{
  <span class="hljs-attr">name</span>: <span class="hljs-string">"vite-plugin-${name}, 
  configResolved() {
   // Called after the Vite config is resolved
  }
}</span>
</code></pre>
<p>Let’s go ahead and write out a basic version of <code>injectVitePlugin</code>:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> type { Plugin } <span class="hljs-keyword">from</span> <span class="hljs-string">"vite"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> injectVitePlugin = (): <span class="hljs-function"><span class="hljs-params">Plugin</span> =&gt;</span> {
  <span class="hljs-comment">//Our prerender plugin to be fleshed out</span>
  <span class="hljs-keyword">const</span> prerenderByDefaultPlugin = { <span class="hljs-attr">name</span>: <span class="hljs-string">""</span> };

  <span class="hljs-keyword">return</span> {
    <span class="hljs-comment">// name follows the pattern vite-plugin-${framework}-${feature}</span>
    <span class="hljs-attr">name</span>: <span class="hljs-string">"vite-plugin-astro-inject-default-prerender"</span>,
    <span class="hljs-attr">configResolved</span>: <span class="hljs-function">(<span class="hljs-params">options</span>) =&gt;</span> {
      <span class="hljs-comment">//Grab the Vite plugins in the resolved config </span>
     <span class="hljs-comment">// and add our plugin as the first in the list </span>
      (options.plugins <span class="hljs-keyword">as</span> Plugin[]).unshift(prerenderByDefaultPlugin);
    },
  };
};
</code></pre>
<p>We will flesh out this basic structure, but first consider that in the astro hooks lifecycle, <code>astro:config:setup</code> runs before <code>astro:config:done</code>.</p>
<p>We're updating the Vite plugins in <code>astro:config:setup</code>. But we're validating the project config in <code>astro:config:done</code>.</p>
<p>We’ll likely run into a race condition here, that is updating the Vite plugin list in <code>astro:config:setup</code> before <code>astro:config:done</code> has wholly validated the project’s config.</p>
<p>How can we resolve this?</p>
<p>Let’s leverage a promise.</p>
<p>We will initialise a promise that’s only resolved after validation is complete, and we will await the promise resolution in <code>injectVitePlugin</code>. Luckily, <code>astro:config:setup</code> can take in async functions. Particularly in the Vite plugin function(s).</p>
<p>Let’s walk through the changes required to achieve this.</p>
<p>First, let’s introduce a <code>ValidationResult</code> type in our <code>types.ts</code> file:</p>
<pre><code class="lang-js"><span class="hljs-comment">// 📂 prerenderByDefault/types.ts</span>

<span class="hljs-keyword">import</span> type { isValidAstroConfig } <span class="hljs-keyword">from</span> <span class="hljs-string">"./isValidAstroConfig"</span>;

<span class="hljs-keyword">export</span> type ValidationResult = ReturnType&lt;<span class="hljs-keyword">typeof</span> isValidAstroConfig&gt;;

<span class="hljs-comment">// ...</span>
</code></pre>
<p>Now, create a new promise in the main <code>index</code> file:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ...</span>
<span class="hljs-keyword">import</span> type { Config, ValidationResult } <span class="hljs-keyword">from</span> <span class="hljs-string">"./types"</span>;

<span class="hljs-keyword">let</span> resolveValidationResult: <span class="hljs-function">(<span class="hljs-params">value: ValidationResult</span>) =&gt;</span> <span class="hljs-keyword">void</span>;

<span class="hljs-keyword">let</span> validationResultPromise = <span class="hljs-keyword">new</span> <span class="hljs-built_in">Promise</span>&lt;ValidationResult&gt;(<span class="hljs-function">(<span class="hljs-params">resolve</span>) =&gt;</span> {
  resolveValidationResult = resolve;
});

<span class="hljs-comment">// ...</span>
</code></pre>
<p>Right after validation is done in <code>astro:config:done</code>, let’s go ahead and resolve the promise with the result of the validation:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ... </span>
<span class="hljs-string">"astro:config:done"</span>(options) {
   <span class="hljs-keyword">const</span> silent = config?.silent ?? <span class="hljs-literal">false</span>;
   <span class="hljs-keyword">const</span> validationResult = isValidAstroConfig(options.config);

   <span class="hljs-comment">// resolve the validation promise</span>
   resolveValidationResult(validationResult);

   <span class="hljs-comment">// ...</span>
}
</code></pre>
<p>Then pass both the integration configuration and validation result promise to <code>injectVitePlugin</code>:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ...</span>
<span class="hljs-attr">plugins</span>: [injectVitePlugin(config, validationResultPromise)],
</code></pre>
<p>We must now update <code>injectVitePlugin</code> to await the validation result promise as shown below:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> type { Plugin } <span class="hljs-keyword">from</span> <span class="hljs-string">"vite"</span>;
<span class="hljs-keyword">import</span> type { Config, ValidationResult } <span class="hljs-keyword">from</span> <span class="hljs-string">"./types"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> injectVitePlugin = <span class="hljs-keyword">async</span> (
  config: Config,
  <span class="hljs-attr">validationResultPromise</span>: <span class="hljs-built_in">Promise</span>&lt;ValidationResult&gt;
): <span class="hljs-built_in">Promise</span>&lt;Plugin | <span class="hljs-literal">null</span>&gt; =&gt; {

  <span class="hljs-comment">// await the validation result promise before continuing</span>
  <span class="hljs-keyword">const</span> validationResult = <span class="hljs-keyword">await</span> validationResultPromise;

  <span class="hljs-comment">// exit if the validation result value is false</span>
  <span class="hljs-keyword">if</span> (!validationResult.value) {
    <span class="hljs-keyword">return</span> <span class="hljs-literal">null</span>;
  }

  <span class="hljs-comment">// TBD ..</span>
  <span class="hljs-keyword">const</span> prerenderByDefaultPlugin = { <span class="hljs-attr">name</span>: <span class="hljs-string">""</span> };

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"vite-plugin-astro-inject-default-prerender"</span>,
    <span class="hljs-attr">configResolved</span>: <span class="hljs-function">(<span class="hljs-params">options</span>) =&gt;</span> {
      (options.plugins <span class="hljs-keyword">as</span> Plugin[]).unshift(prerenderByDefaultPlugin);
    },
  };
};
</code></pre>
<p>Phew! We’ve eradicated the pesky race condition. So our solution is shaping up nicely, eh?</p>
<h3 id="heading-how-to-write-vite-plugins-for-astro">How to write Vite plugins for Astro</h3>
<p>We know what a Vite plugin looks like now. But the core functionality of our integration hasn’t been written yet. This is currently represented by the <code>prerenderByDefaultPlugin</code> variable, that is:</p>
<pre><code class="lang-js"><span class="hljs-comment">// TBD...</span>
  <span class="hljs-keyword">const</span> prerenderByDefaultPlugin = { <span class="hljs-attr">name</span>: <span class="hljs-string">""</span> };
</code></pre>
<p>Let’s change this to be returned from a separate <code>getVitePlugin</code> function:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ...</span>
<span class="hljs-keyword">import</span> { getVitePlugin } <span class="hljs-keyword">from</span> <span class="hljs-string">"./getVitePlugin"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> injectVitePlugin = <span class="hljs-keyword">async</span> (
  config: Config,
  <span class="hljs-attr">validationResultPromise</span>: <span class="hljs-built_in">Promise</span>&lt;ValidationResult&gt;
): <span class="hljs-built_in">Promise</span>&lt;Plugin | <span class="hljs-literal">null</span>&gt; =&gt; {
  <span class="hljs-comment">// ...</span>

  <span class="hljs-keyword">const</span> prerenderByDefaultPlugin = getVitePlugin(config);

  <span class="hljs-comment">// ...</span>
};
</code></pre>
<p>Where <code>getVitePlugin</code> is the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> type { Config } <span class="hljs-keyword">from</span> <span class="hljs-string">"./types"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getVitePlugin = <span class="hljs-function">(<span class="hljs-params">config: Config</span>) =&gt;</span> ({
  <span class="hljs-attr">name</span>: <span class="hljs-string">"vite-plugin-astro-prerender-by-default"</span>,
});
</code></pre>
<h3 id="heading-how-to-parse-and-transforming-asts">How to parse and transforming ASTs</h3>
<p>We want to transform a user’s Astro code and make updates before it is eventually built.</p>
<p>Luckily Vite has a <code>transform</code>  hook we can leverage just for this. Let’s play around with this a bit in our <code>getVitePlugin</code> function:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> type { Plugin } <span class="hljs-keyword">from</span> <span class="hljs-string">"vite"</span>;
<span class="hljs-keyword">import</span> type { Config } <span class="hljs-keyword">from</span> <span class="hljs-string">"./types"</span>;
<span class="hljs-keyword">import</span> { log } <span class="hljs-keyword">from</span> <span class="hljs-string">"./log"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getVitePlugin = (config: Config): <span class="hljs-function"><span class="hljs-params">Plugin</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> silent = config?.silent ?? <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"vite-plugin-astro-prerender-by-default"</span>,
    <span class="hljs-keyword">async</span> transform(code, id) {
      <span class="hljs-comment">// 👀 log the value of the id</span>
      log({
        silent,
        <span class="hljs-attr">message</span>: id,
      });
    },
  };
};
</code></pre>
<p>The <code>transform</code> hook is ideal for transforming individual modules in the build process, and we receive the <code>code</code> in the file as a <code>string</code> and an <code>id</code> representing the <code>string</code> path to the file name.</p>
<p>To test how this works, update the Astro project config to include a <code>server</code> output.</p>
<pre><code class="lang-js"><span class="hljs-keyword">export</span> <span class="hljs-keyword">default</span> defineConfig({
  <span class="hljs-attr">output</span>: <span class="hljs-string">"server"</span>,
  <span class="hljs-attr">integrations</span>: [prerenderByDefault()],
});
</code></pre>
<p>Then add an adapter to handle server-side rendering with:</p>
<pre><code class="lang-bash">npx astro add netlify
</code></pre>
<p>We may now explore the log from <code>getVitePlugin</code> by running <code>npm run build</code> from the terminal.</p>
<p>Notice how many more files are transformed than just the user’s <code>.astro</code> pages.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-12-at-09.18.14.png" alt="Exploring the list of transformed files." width="849" height="653" loading="lazy">
<em>Exploring the list of transformed files.</em></p>
<p>Most of the files here are related to Astro internals. So we must only concern ourselves with the user’s <code>.astro</code> pages. We want to transform those files while leaving everything else as is.</p>
<p>Let’s add a simple conditional:</p>
<pre><code class="lang-js"><span class="hljs-comment">// ... </span>
  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"vite-plugin-astro-prerender-by-default"</span>,
    <span class="hljs-keyword">async</span> transform(code, id) {
      <span class="hljs-comment">// 👀 filter out other file types</span>
      <span class="hljs-keyword">if</span> (!id.endsWith(<span class="hljs-string">".astro"</span>)) {
        <span class="hljs-keyword">return</span>;
      }

      <span class="hljs-comment">// log the value of the id</span>
      log({
        silent,
        <span class="hljs-attr">message</span>: id,
      });
    },
  };
</code></pre>
<p>Now, rerun the build, and we should have just the user’s <code>.astro</code> page files.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-12-at-09.22.30.png" alt="Logging the project page files." width="799" height="285" loading="lazy">
<em>Logging the project page files.</em></p>
<p>This is excellent.</p>
<p>Just after the conditional, we can get on with parsing the code. To do this, we will leverage the <code>parse</code> utility exported from Astro’s compiler as shown below:</p>
<pre><code class="lang-js">    <span class="hljs-comment">// ... </span>
    <span class="hljs-keyword">async</span> transform(code, id) {
      <span class="hljs-keyword">if</span> (!id.endsWith(<span class="hljs-string">".astro"</span>)) {
        <span class="hljs-keyword">return</span>;
      }

      <span class="hljs-comment">// 👀 </span>
      <span class="hljs-keyword">const</span> { ast } = <span class="hljs-keyword">await</span> parse(code);

      <span class="hljs-comment">// 👀 logs for debugging </span>
      log({
        silent,
        <span class="hljs-attr">message</span>: <span class="hljs-string">"Parsed AST"</span>,
      });

      <span class="hljs-built_in">console</span>.log(ast);
    }
</code></pre>
<p>This project only has a single page in <code>src/index.astro</code>. So, essentially, only that page will be transformed.</p>
<p>Here’s the content of the page:</p>
<pre><code class="lang-js">---
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>Astro<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>Astro<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>Here’s the corresponding AST logged to the console:</p>
<pre><code class="lang-js">{
  <span class="hljs-attr">type</span>: <span class="hljs-string">'root'</span>,
  <span class="hljs-attr">children</span>: [
    { <span class="hljs-attr">type</span>: <span class="hljs-string">'frontmatter'</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'\n'</span>, <span class="hljs-attr">position</span>: [<span class="hljs-built_in">Object</span>] },
    {
      <span class="hljs-attr">type</span>: <span class="hljs-string">'element'</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">'html'</span>,
      <span class="hljs-attr">attributes</span>: [<span class="hljs-built_in">Array</span>],
      <span class="hljs-attr">children</span>: [<span class="hljs-built_in">Array</span>]
    },
    { <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'\n'</span>, <span class="hljs-attr">position</span>: [<span class="hljs-built_in">Object</span>] }
  ]
}
</code></pre>
<p>Every parsed AST will have a <code>root</code> element. An empty file will have the shape:</p>
<pre><code class="lang-js">{ <span class="hljs-attr">type</span>: <span class="hljs-string">'root'</span> }
</code></pre>
<p>Knowing this, we can build out our parsing logic. But we need a way to walk the entire AST. </p>
<p>We could write a sophisticated function to loop over every element in the tree. But we can leverage the <code>walk</code> utility from the Astro compiler, which will traverse every node in the tree, and we could perform any actions on a specified node via a callback.</p>
<p>Let’s take that for a spin by adding the following:</p>
<pre><code class="lang-js"><span class="hljs-keyword">const</span> { ast } = <span class="hljs-keyword">await</span> parse(code);

<span class="hljs-comment">// 👀</span>
walk(ast, <span class="hljs-function">(<span class="hljs-params">node</span>) =&gt;</span> {
  <span class="hljs-built_in">console</span>.log(<span class="hljs-string">"=========== \n"</span>, node);
});
</code></pre>
<p>Inspect the logs, and we should have the different nodes logged to the console, for example:</p>
<pre><code class="lang-js">=========== 
 {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'root'</span>,
  <span class="hljs-attr">children</span>: [
    { <span class="hljs-attr">type</span>: <span class="hljs-string">'frontmatter'</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'\n'</span>, <span class="hljs-attr">position</span>: [<span class="hljs-built_in">Object</span>] },
    {
      <span class="hljs-attr">type</span>: <span class="hljs-string">'element'</span>,
      <span class="hljs-attr">name</span>: <span class="hljs-string">'html'</span>,
      <span class="hljs-attr">attributes</span>: [<span class="hljs-built_in">Array</span>],
      <span class="hljs-attr">children</span>: [<span class="hljs-built_in">Array</span>]
    },
    { <span class="hljs-attr">type</span>: <span class="hljs-string">'text'</span>, <span class="hljs-attr">value</span>: <span class="hljs-string">'\n'</span>, <span class="hljs-attr">position</span>: [<span class="hljs-built_in">Object</span>] }
  ]
}
=========== 
 {
  <span class="hljs-attr">type</span>: <span class="hljs-string">'frontmatter'</span>,
  <span class="hljs-attr">value</span>: <span class="hljs-string">'\n'</span>,
  <span class="hljs-attr">position</span>: {
    <span class="hljs-attr">start</span>: { <span class="hljs-attr">line</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">column</span>: <span class="hljs-number">1</span>, <span class="hljs-attr">offset</span>: <span class="hljs-number">0</span> },
    <span class="hljs-attr">end</span>: { <span class="hljs-attr">line</span>: <span class="hljs-number">2</span>, <span class="hljs-attr">column</span>: <span class="hljs-number">4</span>, <span class="hljs-attr">offset</span>: <span class="hljs-number">7</span> }
  }
}
=========== 
<span class="hljs-comment">// ... see logs</span>
</code></pre>
<p>It’s game time. Let’s go ahead and write out the complete code, which involves:</p>
<ul>
<li>Walking the AST</li>
<li>Checking if the file has a frontmatter</li>
<li>Checking if the file already has a <code>prerender</code> export in its frontmatter. For this, we will use <a target="_blank" href="https://github.com/guybedford/es-module-lexer#readme">es-module-lexer</a> , which outputs the list of exports of import specifiers</li>
<li>Adding <code>export const prerender = true</code> to the code where required</li>
<li>After transforming the AST, that is adding <code>export const prerender = true</code> where needed, we will return the AST to code via the <code>serialize</code> utility from the Astro compiler.</li>
</ul>
<p>Here we go:</p>
<pre><code class="lang-js"><span class="hljs-keyword">import</span> type { Plugin } <span class="hljs-keyword">from</span> <span class="hljs-string">"vite"</span>;
<span class="hljs-keyword">import</span> type { Config } <span class="hljs-keyword">from</span> <span class="hljs-string">"./types"</span>;
<span class="hljs-keyword">import</span> { parse } <span class="hljs-keyword">from</span> <span class="hljs-string">"@astrojs/compiler"</span>;
<span class="hljs-keyword">import</span> { walk, is, serialize } <span class="hljs-keyword">from</span> <span class="hljs-string">"@astrojs/compiler/utils"</span>;
<span class="hljs-keyword">import</span> { parse <span class="hljs-keyword">as</span> parseESModuleLexer } <span class="hljs-keyword">from</span> <span class="hljs-string">"es-module-lexer"</span>;

<span class="hljs-keyword">import</span> { log } <span class="hljs-keyword">from</span> <span class="hljs-string">"./log"</span>;

<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> getVitePlugin = (config: Config): <span class="hljs-function"><span class="hljs-params">Plugin</span> =&gt;</span> {
  <span class="hljs-keyword">const</span> silent = config?.silent ?? <span class="hljs-literal">false</span>;

  <span class="hljs-keyword">return</span> {
    <span class="hljs-attr">name</span>: <span class="hljs-string">"vite-plugin-astro-prerender-by-default"</span>,
    <span class="hljs-keyword">async</span> transform(code, id) {
      <span class="hljs-keyword">if</span> (!id.endsWith(<span class="hljs-string">".astro"</span>)) {
        <span class="hljs-keyword">return</span>;
      }

      <span class="hljs-keyword">const</span> { ast } = <span class="hljs-keyword">await</span> parse(code);

      walk(ast, <span class="hljs-function">(<span class="hljs-params">node</span>) =&gt;</span> {
        <span class="hljs-keyword">if</span> (is.root(node)) {
          <span class="hljs-keyword">const</span> firstChildNode = node.children?.[<span class="hljs-number">0</span>];

          <span class="hljs-comment">//Check that a frontmatter exists as the first child node</span>
          <span class="hljs-keyword">if</span> (firstChildNode?.type === <span class="hljs-string">"frontmatter"</span>) {
            <span class="hljs-comment">//Using es-module-lexer, get the list of exports</span>
            <span class="hljs-keyword">const</span> [, <span class="hljs-built_in">exports</span>] = parseESModuleLexer(firstChildNode.value);

            <span class="hljs-comment">//Check if any export is named "prerender". "n" stands for "name."</span>
            <span class="hljs-keyword">if</span> (<span class="hljs-built_in">exports</span>.some(<span class="hljs-function">(<span class="hljs-params">e</span>) =&gt;</span> e.n === <span class="hljs-string">"prerender"</span>)) {
              log({
                silent,
                <span class="hljs-attr">message</span>: <span class="hljs-string">"'prerender' export found. Skipping"</span>,
              });

              <span class="hljs-comment">// exit - let whatever prerender value is exported take effect</span>
              <span class="hljs-keyword">return</span>;
            }

            <span class="hljs-comment">// add prerender export for the static build, i.e., "export const prerender = true."</span>
            <span class="hljs-comment">// note that we concatenate this to whatever the current string value of the node is</span>
            firstChildNode.value = <span class="hljs-string">`\nexport const prerender = true; \n <span class="hljs-subst">${firstChildNode.value}</span>`</span>;

            log({
              silent,
              <span class="hljs-attr">message</span>: <span class="hljs-string">"Added 'prerender' export to frontmatter"</span>,
            });
          } <span class="hljs-keyword">else</span> {
            <span class="hljs-comment">// No frontmatter in this astro component. Add frontmatter node and default export</span>
            log({
              silent,
              <span class="hljs-attr">message</span>: <span class="hljs-string">"No frontmatter, going ahead to add one"</span>,
            });

            <span class="hljs-comment">// "unshift" to add this to the start of the list, i.e., the first child</span>
            node.children.unshift({
              <span class="hljs-attr">type</span>: <span class="hljs-string">"frontmatter"</span>,
              <span class="hljs-attr">value</span>: <span class="hljs-string">"\nexport const prerender = true\n"</span>,
            });
          }
        }
      });

      <span class="hljs-comment">//serialise the AST and return the result</span>
      <span class="hljs-keyword">const</span> result = serialize(ast);

      <span class="hljs-comment">// added for the reader's debugging</span>
      <span class="hljs-built_in">console</span>.log(result);
      <span class="hljs-keyword">return</span> result;
    },
  };
};
</code></pre>
<p>The code block above is annotated. Please take a close look at it. If something is unclear, add some <code>console.log</code>s. Together with the annotation, I’m sure you’ll understand the explanations even better.</p>
<h3 id="heading-manual-testing">Manual testing</h3>
<p>We have our solution complete. Now, let’s test it. First, build the project with <code>npm run build</code>, and even though we have a <code>server</code> output in the Astro config, we now have the <code>index.astro</code> page statically built by default.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-12-at-16.10.58@2x.png" alt="Pre-rendering the index.astro static route." width="1409" height="426" loading="lazy">
<em>Pre-rendering the index.astro static route.</em></p>
<p>To render a server-side page, we need to manually add <code>export const prerender = false</code>.</p>
<p>Create a new page with identical content as <code>index.astro</code> and have the <code>prerender</code> export.</p>
<pre><code class="lang-js">---
<span class="hljs-keyword">export</span> <span class="hljs-keyword">const</span> prerender = <span class="hljs-literal">false</span>;
---

<span class="xml"><span class="hljs-tag">&lt;<span class="hljs-name">html</span> <span class="hljs-attr">lang</span>=<span class="hljs-string">"en"</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">head</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">charset</span>=<span class="hljs-string">"utf-8"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">link</span> <span class="hljs-attr">rel</span>=<span class="hljs-string">"icon"</span> <span class="hljs-attr">type</span>=<span class="hljs-string">"image/svg+xml"</span> <span class="hljs-attr">href</span>=<span class="hljs-string">"/favicon.svg"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"viewport"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">"width=device-width"</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">meta</span> <span class="hljs-attr">name</span>=<span class="hljs-string">"generator"</span> <span class="hljs-attr">content</span>=<span class="hljs-string">{Astro.generator}</span> /&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">title</span>&gt;</span>SSR<span class="hljs-tag">&lt;/<span class="hljs-name">title</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">head</span>&gt;</span>
  <span class="hljs-tag">&lt;<span class="hljs-name">body</span>&gt;</span>
    <span class="hljs-tag">&lt;<span class="hljs-name">h1</span>&gt;</span>SSR<span class="hljs-tag">&lt;/<span class="hljs-name">h1</span>&gt;</span>
  <span class="hljs-tag">&lt;/<span class="hljs-name">body</span>&gt;</span>
<span class="hljs-tag">&lt;/<span class="hljs-name">html</span>&gt;</span></span>
</code></pre>
<p>Now rerun the build and notice how only the <code>index.astro</code> page is pre-rendered.</p>
<p><img src="https://blog.ohansemmanuel.com/content/images/2023/06/CleanShot-2023-04-12-at-16.17.15@2x.png" alt="Skipping prerender when export is found." width="1340" height="627" loading="lazy">
<em>Skipping prerender when export is found.</em></p>
<h2 id="heading-how-to-build-renderers-and-library-integrations">How to Build Renderers and Library Integrations</h2>
<p>As stated earlier in the chapter, the focus here is feature integrations. For building renderers and library integrations, I strongly recommend taking a look at the source code for popular integrations such as:</p>
<ul>
<li>The <a target="_blank" href="https://github.com/withastro/astro/tree/main/packages/integrations/react">React</a> , <a target="_blank" href="https://github.com/withastro/astro/tree/main/packages/integrations/preact">Preact</a>or <a target="_blank" href="https://github.com/withastro/astro/tree/main/packages/integrations/vue">Vue</a> renderer integrations.</li>
<li>The <a target="_blank" href="https://github.com/withastro/astro/tree/main/packages/integrations/tailwind">Tailwind</a> or <a target="_blank" href="https://github.com/withastro/astro/tree/main/packages/integrations/partytown">partytown</a> library integrations.</li>
</ul>
<p>Most of these integrations are barely 100 lines of code at the core. Dig into them!</p>
<h2 id="heading-wrapping-up-this-chapter-7">Wrapping Up This Chapter</h2>
<p>Building custom integrations is definitely something you can do. Heck! Writing compilers isn’t a prerequisite.</p>
<p>Building upon the explanations and examples discussed here, we’ve seen how mere mortals like us can reach down into the internals of Astro and bend it to our will. Now, put this knowledge to practice.</p>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/image-141.png" alt="Image" width="600" height="400" loading="lazy">
<em>The end.</em></p>
<h1 id="heading-conclusion">Conclusion</h1>
<p>Look who made it to the end! 🚀</p>
<p>Yes, you!</p>
<p>I’ve poured my heart into these chapters, and I’m sure you’ve learned a thing or two.</p>
<p>So, where do you go next?</p>
<p>Firstly, I strongly recommend visiting the official Astro <a target="_blank" href="https://astro.build/">documentation</a>. It’s a great resource that’ll benefit you long-term as you develop Astro applications.</p>
<p>Secondly, ponder the features that make Astro stand out:</p>
<ul>
<li><strong>Leverage Component Islands</strong>: A new web architecture for building faster websites.</li>
<li><strong>Zero JS, by default</strong>: Keep applications fast with no JS runtime overhead.</li>
<li><strong>Edge-ready</strong>: Deploy anywhere, even global edge runtimes like Deno or Cloudflare.</li>
<li><strong>Incredibly customizable</strong>: Use Tailwind, MDX, and 100+ other <a target="_blank" href="https://astro.build/integrations/">integrations</a>.</li>
<li><strong>Bring your own framework</strong>: Supports React, Preact, Vue, Svelte, Solid, Lit and more.</li>
</ul>
<h2 id="heading-helpful-links-and-resources">Helpful links and resources</h2>
<ul>
<li>⚠️ <a target="_blank" href="https://www.ohansemmanuel.com/newsletter">Stay in touch with my work</a> and be first to know about updates to this book (and my other writings). <a target="_blank" href="https://www.ohansemmanuel.com/newsletter">Do so here</a>.</li>
<li><a target="_blank" href="https://astro.build/integrations/">Astro integrations</a>: explore these to add more functionality to your Astro applications.</li>
<li><a target="_blank" href="https://astro.build/themes">Astro themes</a>: explore themes you can start your new project with.  </li>
</ul>
<p>Until next time,</p>
<p><a target="_blank" href="https://www.ohansemmanuel.com/">Ohans E.</a>🥂</p>
<h2 id="heading-want-to-get-the-ebook-1">Want to get the ebook?</h2>
<p><img src="https://www.freecodecamp.org/news/content/images/2023/06/book-cover-transparent-1.png" alt="Image" width="600" height="400" loading="lazy">
<em><a target="_blank" href="https://github.com/understanding-astro/understanding-astro-book">Download ebooks on Github</a></em></p>
<ul>
<li>500+ pages of value</li>
<li>4+ practical project chapters</li>
<li>100+ carefully crafted illustrations and images</li>
<li>Learn techniques to build faster applications </li>
<li><strong>Integrate React, Svelte, Vue, Tailwind</strong> and more into an Astro project </li>
<li>Learn to build your own <strong>component islands implementation</strong> from scratch</li>
<li>Learn to <strong>build fullstack applications with Astro</strong> (without sacrificing performance) </li>
<li>Go <strong>beyond the basics</strong> and parse Astro code into ASTs and build custom project features </li>
</ul>
<p><em><a target="_blank" href="https://ohans.me/ua-github">Download the free ebook on Github.</a></em> </p>
 ]]>
                </content:encoded>
            </item>
        
    </channel>
</rss>
